summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--lib/generator.rb61
2 files changed, 36 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 9f03661c7..cbd37bb6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Dec 30 18:27:00 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+
+ * lib/generator.rb: uses Mutex instead of Thread.critical.
+ [ruby-dev:28184]
+
Fri Dec 30 18:22:42 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
* gc.c (garbage_collect): mark objects refered from aborting threads.
diff --git a/lib/generator.rb b/lib/generator.rb
index 241987fab..19f238544 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?