summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorocean <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-12-30 09:29:07 +0000
committerocean <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-12-30 09:29:07 +0000
commit2c1706fffb3fed17085af23de26ce84ed8ebae1a (patch)
tree94e61f683c54f3f00a7c0fe6ff3d97e396c57955 /lib
parentdc94d09ad5866ed445683f253bea343c383af6dc (diff)
* lib/generator.rb: uses Mutex instead of Thread.critical.
[ruby-dev:28184] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9773 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/generator.rb61
1 files changed, 31 insertions, 30 deletions
diff --git a/lib/generator.rb b/lib/generator.rb
index 241987faba..19f2385449 100644
--- a/lib/generator.rb
+++ b/lib/generator.rb
@@ -23,6 +23,7 @@
#
# See the respective classes for examples of usage.
+require "thread"
#
# Generator converts an internal iterator (i.e. an Enumerable object)
@@ -71,17 +72,24 @@ class Generator
end
@index = 0
@queue = []
+ @mutex = Mutex.new
+ @main_cond = ConditionVariable.new
+ @loop_cond = ConditionVariable.new
+ entered = false
@loop_thread = Thread.new do
- Thread.stop
- begin
- @block.call(self)
- rescue
- @main_thread.raise
- ensure
- @main_thread.wakeup
+ @mutex.synchronize do
+ entered = true
+ @loop_cond.wait(@mutex)
+ begin
+ @block.call(self)
+ rescue
+ @main_thread.raise $!
+ ensure
+ @main_cond.signal
+ end
end
end
- Thread.pass until @loop_thread.stop?
+ Thread.pass until entered && !@mutex.locked?
self
end
@@ -90,33 +98,26 @@ class Generator
if Thread.current != @loop_thread
raise "should be called in Generator.new{|g| ... }"
end
- Thread.critical = true
- begin
- @queue << value
- @main_thread.wakeup
- Thread.stop
- ensure
- Thread.critical = false
- end
+ @queue << value
+ @main_cond.signal
+ @loop_cond.wait(@mutex)
self
end
# Returns true if the generator has reached the end.
def end?
- if @queue.empty?
- if @main_thread
- raise "should not be called in Generator.new{|g| ... }"
- end
- Thread.critical = true
- begin
- @main_thread = Thread.current
- @loop_thread.wakeup
- Thread.stop
- rescue ThreadError
- # ignore
- ensure
- @main_thread = nil
- Thread.critical = false
+ @mutex.synchronize do
+ if @queue.empty? && @loop_thread.alive?
+ if @main_thread
+ raise "should not be called in Generator.new{|g| ... }"
+ end
+ begin
+ @main_thread = Thread.current
+ @loop_cond.signal
+ @main_cond.wait(@mutex)
+ ensure
+ @main_thread = nil
+ end
end
end
@queue.empty?