Created
November 30, 2012 16:21
-
-
Save kosaki/4176770 to your computer and use it in GitHub Desktop.
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
| diff --git a/ChangeLog b/ChangeLog | |
| index f2f2cf1..378c63b 100644 | |
| --- a/ChangeLog | |
| +++ b/ChangeLog | |
| @@ -1,3 +1,10 @@ | |
| +Sat Dec 1 01:19:34 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com> | |
| + | |
| + * lib/thread.rb (ConditionVariable#broadcast): protect from | |
| + async interrupt by using Thread.async_interrupt_timing. | |
| + * lib/thread.rb (ConditionVariable#signal): ditto. | |
| + * lib/thread.rb (ConditionVariable#wait): ditto. | |
| + | |
| Fri Nov 30 22:44:14 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com> | |
| * vm_core.h (rb_vm_struct): add thread_destruct_lock field. | |
| diff --git a/lib/thread.rb b/lib/thread.rb | |
| index 0a5d1f4..1af0a19 100644 | |
| --- a/lib/thread.rb | |
| +++ b/lib/thread.rb | |
| @@ -63,15 +63,18 @@ class ConditionVariable | |
| # even if no other thread doesn't signal. | |
| # | |
| def wait(mutex, timeout=nil) | |
| - begin | |
| - # TODO: mutex should not be used | |
| - @waiters_mutex.synchronize do | |
| - @waiters.push(Thread.current) | |
| - end | |
| - mutex.sleep timeout | |
| - ensure | |
| - @waiters_mutex.synchronize do | |
| - @waiters.delete(Thread.current) | |
| + Thread.async_interrupt_timing(StandardError => :never) do | |
| + begin | |
| + Thread.async_interrupt_timing(StandardError => :on_blocking) do | |
| + @waiters_mutex.synchronize do | |
| + @waiters.push(Thread.current) | |
| + end | |
| + mutex.sleep timeout | |
| + end | |
| + ensure | |
| + @waiters_mutex.synchronize do | |
| + @waiters.delete(Thread.current) | |
| + end | |
| end | |
| end | |
| self | |
| @@ -81,11 +84,13 @@ class ConditionVariable | |
| # Wakes up the first thread in line waiting for this lock. | |
| # | |
| def signal | |
| - begin | |
| - t = @waiters_mutex.synchronize {@waiters.shift} | |
| - t.run if t | |
| - rescue ThreadError | |
| - retry | |
| + Thread.async_interrupt_timing(RuntimeError => :on_blocking) do | |
| + begin | |
| + t = @waiters_mutex.synchronize {@waiters.shift} | |
| + t.run if t | |
| + rescue ThreadError | |
| + retry # t was alread dead? | |
| + end | |
| end | |
| self | |
| end | |
| @@ -94,16 +99,17 @@ class ConditionVariable | |
| # Wakes up all threads waiting for this lock. | |
| # | |
| def broadcast | |
| - # TODO: incomplete | |
| - waiters0 = nil | |
| - @waiters_mutex.synchronize do | |
| - waiters0 = @waiters.dup | |
| - @waiters.clear | |
| - end | |
| - for t in waiters0 | |
| - begin | |
| - t.run | |
| - rescue ThreadError | |
| + Thread.async_interrupt_timing(RuntimeError => :on_blocking) do | |
| + waiters0 = nil | |
| + @waiters_mutex.synchronize do | |
| + waiters0 = @waiters.dup | |
| + @waiters.clear | |
| + end | |
| + for t in waiters0 | |
| + begin | |
| + t.run | |
| + rescue ThreadError | |
| + end | |
| end | |
| end | |
| self |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment