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 hidden or 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 # <= This should be threadsafe by its very nature | |
| 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 | |
| baz1 = -1 | |
| baz2 = -1 | |
| count = 0 | |
| last_one = "" | |
| show_once = true | |
| while baz1 == baz2 | |
| last_one = "f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}" | |
| f.bar = nil | |
| wait_til = Time.now + 0.01 | |
| Thread.new {sleep (wait_til - Time.now); baz1 = f.baz } | |
| Thread.new {sleep (wait_til - Time.now); baz2 = f.baz } | |
| sleep 0.02 | |
| count += 1 | |
| if count == 100 | |
| puts "working: #{last_one}" | |
| count = 0 | |
| end | |
| if show_once | |
| show_once = false | |
| # only want to run these after the classes have had a chance to instnatiate the mutexes, | |
| # not force them to be instantiated (thus negating the reason for the test) | |
| puts "Class mutex: #{f.class.threadsafe_class_mutex}" | |
| puts "instance mutex: #{f.threadsafe_mutex}" | |
| puts "instance mutex: #{f2.threadsafe_mutex}" # Just to verify instances are getting their own mutexes | |
| end | |
| end | |
| puts | |
| puts "Thread collision" | |
| puts "previous: #{last_one}" # Just to prove it's not remembering value from last iteration but is a real collision | |
| puts "current: f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment