Class: Generator
- Inherits:
-
Object
- Object
- Generator
- Includes:
- Enumerable
- Defined in:
- lib/s3sync/thread_generator.rb
Overview
Generator converts an internal iterator (i.e. an Enumerable object) to an external iterator.
Example
require 'generator'
# Generator from an Enumerable object
g = Generator.new(['A', 'B', 'C', 'Z'])
while g.next?
puts g.next
end
# Generator from a block
g = Generator.new { |g|
for i in 'A'..'C'
g.yield i
end
g.yield 'Z'
}
# The same result as above
while g.next?
puts g.next
end
Instance Method Summary collapse
-
#current ⇒ Object
Returns the element at the current position.
-
#each ⇒ Object
Rewinds the generator and enumerates the elements.
-
#end? ⇒ Boolean
Returns true if the generator has reached the end.
-
#index ⇒ Object
Returns the current index (position) counting from zero.
-
#initialize(enum = nil, &block) ⇒ Generator
constructor
Creates a new generator either from an Enumerable object or from a block.
-
#next ⇒ Object
Returns the element at the current position and moves forward.
-
#next? ⇒ Boolean
Returns true if the generator has not reached the end yet.
-
#pos ⇒ Object
Returns the current index (position) counting from zero.
-
#rewind ⇒ Object
Rewinds the generator.
-
#yield(value) ⇒ Object
Yields an element to the generator.
Constructor Details
#initialize(enum = nil, &block) ⇒ Generator
Creates a new generator either from an Enumerable object or from a block.
In the former, block is ignored even if given.
In the latter, the given block is called with the generator itself, and expected to call the yield
method for each element.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/s3sync/thread_generator.rb', line 66 def initialize(enum = nil, &block) if enum @block = proc{|g| enum.each{|value| g.yield value}} else @block = block end @index = 0 @queue = [] @main_thread = nil @loop_thread.kill if defined?(@loop_thread) @loop_thread = Thread.new do Thread.stop begin @block.call(self) rescue @main_thread.raise $! ensure @main_thread.wakeup end end Thread.pass until @loop_thread.stop? self end |
Instance Method Details
#current ⇒ Object
Returns the element at the current position.
150 151 152 153 |
# File 'lib/s3sync/thread_generator.rb', line 150 def current raise EOFError.new("no more elements available") if end? @queue.first end |
#each ⇒ Object
Rewinds the generator and enumerates the elements.
162 163 164 165 166 167 168 |
# File 'lib/s3sync/thread_generator.rb', line 162 def each rewind until end? yield self.next end self end |
#end? ⇒ Boolean
Returns true if the generator has reached the end.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/s3sync/thread_generator.rb', line 107 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 end end @queue.empty? end |
#index ⇒ Object
Returns the current index (position) counting from zero.
133 134 135 |
# File 'lib/s3sync/thread_generator.rb', line 133 def index @index end |
#next ⇒ Object
Returns the element at the current position and moves forward.
143 144 145 146 147 |
# File 'lib/s3sync/thread_generator.rb', line 143 def next raise EOFError.new("no more elements available") if end? @index += 1 @queue.shift end |
#next? ⇒ Boolean
Returns true if the generator has not reached the end yet.
128 129 130 |
# File 'lib/s3sync/thread_generator.rb', line 128 def next? !end? end |
#pos ⇒ Object
Returns the current index (position) counting from zero.
138 139 140 |
# File 'lib/s3sync/thread_generator.rb', line 138 def pos @index end |
#rewind ⇒ Object
Rewinds the generator.
156 157 158 159 |
# File 'lib/s3sync/thread_generator.rb', line 156 def rewind initialize(nil, &@block) if @index.nonzero? self end |
#yield(value) ⇒ Object
Yields an element to the generator.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/s3sync/thread_generator.rb', line 91 def yield(value) 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 self end |