Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Stops collisions but it's ugly
require 'thread'
module ThreadSafe
def self.included(base)
base.extend(ThreadSafeClassMethods)
base.threadsafe_class_mutex = Mutex.new
end
module ThreadSafeClassMethods
attr_accessor :threadsafe_class_mutex
end
def threadsafe_mutex
self.class.threadsafe_class_mutex.synchronize {
@mutex ||= Mutex.new
}
end
end
class Foo
include ThreadSafe
attr_accessor :bar
def baz
threadsafe_mutex.synchronize {
@bar ||= rand(10000000000)
}
end
end
f = Foo.new
f2 = Foo.new
lastBaz1 = -2
lastBaz2 = -2
baz1 = -1
baz2 = -1
count = 0
show_once = true
while baz1 == baz2
last_one = "f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}"
f = Foo.new
lastBaz1, lastBaz2 = baz1, baz2
t1 = Thread.new {sleep ((Time.now + 0.01 )- Time.now); baz1 = f.baz }
t2 = Thread.new {sleep ((Time.now + 0.01) - Time.now); baz2 = f.baz }
# make sure both threads are done
time_out = 0
sleep 0.01 while (baz2 == lastBaz2 || baz1 == lastBaz1) && (time_out += 1) < 10
if time_out == 10
# Make sure it wasn't an error in the thread that caused the timeout
t1.join
t2.join
puts "timeout reached"
break
end
puts "#{f.threadsafe_mutex}: #{f.bar}" if (count+=1) % 100 == 0
GC.start if count % 100 == 0
# Verify instances are getting their own mutexes
if show_once
show_once = false
puts "Class mutex: #{f.class.threadsafe_class_mutex}"
puts "instance mutex: #{f.threadsafe_mutex}"
puts "instance mutex: #{f2.threadsafe_mutex}"
end
end
puts
puts "Thread collision: should never get here"
puts "previous: #{last_one}" # <= Prove it's not remembering value from last iteration but is a real collision
puts "current: f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}"
puts "Class mutex: #{f.class.threadsafe_class_mutex}"
puts "instance mutex: #{f.threadsafe_mutex}"
puts "instance mutex: #{f2.threadsafe_mutex}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.