Created
June 17, 2011 13:30
-
-
Save mikbe/1031419 to your computer and use it in GitHub Desktop.
Stops collisions but it's ugly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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