Class: DFuzz::Generator
- Inherits:
-
Enumerator
- Object
- Enumerator
- DFuzz::Generator
- Includes:
- Enumerable
- Defined in:
- lib/dfuzz/generator18.rb,
lib/dfuzz/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
Direct Known Subclasses
Instance Method Summary collapse
-
#current ⇒ Object
Returns the element at the current position.
-
#each ⇒ Object
Rewinds the generator and enumerates the elements.
- #empty? ⇒ Boolean
-
#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.
-
#shift ⇒ Object
def to_a; self; end.
-
#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.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/dfuzz/generator18.rb', line 67 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.
151 152 153 154 |
# File 'lib/dfuzz/generator18.rb', line 151 def current raise EOFError.new("no more elements available") if end? @queue.first end |
#each ⇒ Object
Rewinds the generator and enumerates the elements.
163 164 165 166 167 168 169 |
# File 'lib/dfuzz/generator18.rb', line 163 def each rewind until end? yield self.next end self end |
#empty? ⇒ Boolean
14 |
# File 'lib/dfuzz/generator.rb', line 14 def empty?; !self.next?; end |
#end? ⇒ Boolean
Returns true if the generator has reached the end.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/dfuzz/generator18.rb', line 108 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.
134 135 136 |
# File 'lib/dfuzz/generator18.rb', line 134 def index @index end |
#next ⇒ Object
Returns the element at the current position and moves forward.
144 145 146 147 148 |
# File 'lib/dfuzz/generator18.rb', line 144 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.
129 130 131 132 133 134 135 136 |
# File 'lib/dfuzz/generator18.rb', line 129 def next? begin self.peek true rescue StopIteration false end end |
#pos ⇒ Object
Returns the current index (position) counting from zero.
139 140 141 |
# File 'lib/dfuzz/generator18.rb', line 139 def pos @index end |
#rewind ⇒ Object
Rewinds the generator.
157 158 159 160 |
# File 'lib/dfuzz/generator18.rb', line 157 def rewind initialize(nil, &@block) if @index.nonzero? self end |
#shift ⇒ Object
def to_a; self; end
13 |
# File 'lib/dfuzz/generator.rb', line 13 def shift; next? ? self.next : nil; end |
#yield(value) ⇒ Object
Yields an element to the generator.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/dfuzz/generator18.rb', line 92 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 |