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