Class: Generator
- Inherits:
-
Object
- Object
- Generator
- Includes:
- Enumerable
- Defined in:
- lib/sequence/generator.rb
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.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/sequence/generator.rb', line 75 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.
159 160 161 162 |
# File 'lib/sequence/generator.rb', line 159 def current raise EOFError.new("no more elements available") if end? @queue.first end |
#each ⇒ Object
Rewinds the generator and enumerates the elements.
171 172 173 174 175 176 177 |
# File 'lib/sequence/generator.rb', line 171 def each rewind until end? yield self.next end self end |
#end? ⇒ Boolean
Returns true if the generator has reached the end.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/sequence/generator.rb', line 116 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.
142 143 144 |
# File 'lib/sequence/generator.rb', line 142 def index @index end |
#next ⇒ Object
Returns the element at the current position and moves forward.
152 153 154 155 156 |
# File 'lib/sequence/generator.rb', line 152 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.
137 138 139 |
# File 'lib/sequence/generator.rb', line 137 def next? !end? end |
#pos ⇒ Object
Returns the current index (position) counting from zero.
147 148 149 |
# File 'lib/sequence/generator.rb', line 147 def pos @index end |
#rewind ⇒ Object
Rewinds the generator.
165 166 167 168 |
# File 'lib/sequence/generator.rb', line 165 def rewind initialize(nil, &@block) if @index.nonzero? self end |
#yield(value) ⇒ Object
Yields an element to the generator.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/sequence/generator.rb', line 100 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 |