Hello. Please add this to quiz's rule.
Generator should suspend current calculation, and
resume it when next() is called. (I uses @queue as
array, but this is just for insurance. normally
@queue should not contain multiple values)
//////////////////////////////////////////
require "test/unit"
require "generator"
class TestGenerator < Test::Unit::TestCase
class C
def value=(x)
@value = x
end
def each
loop do
yield @value
end
end
end
def test_realtime
c = C.new
g = Generator.new(c)
3.times do |i|
c.value = i
assert_equal(i, g.next())
end
end
end
//////////////////////////////////////////
And python supports generator natively,
this behaves like HEAD's Generator class.
def generator():
global value
while True:
yield value
g = generator()
for i in xrange(3):
value = i
print g.next()
////////////////////////////////////////////
And this one is Java version.
abstract class CoRoutine
{
private final Thread _thread;
private final Object _lock = new Object();
private java.util.LinkedList _list = new java.util.LinkedList();
private boolean _terminated = false;
public CoRoutine()
{
final Object first_lock = new Object();
_thread = new Thread()
{
public void run()
{
synchronized(_lock)
{
synchronized (first_lock)
{
first_lock.notify();
}
try
{
_lock.wait();
}
catch (InterruptedException e)
{
throw new RuntimeException(e); // ???
}
try
{
CoRoutine.this.run();
}
finally
{
_terminated = true;
_lock.notify();
}
}
}
};
_thread.setDaemon(true);
synchronized(first_lock)
{
_thread.start();
try
{
first_lock.wait();
}
catch (InterruptedException e)
{
throw new RuntimeException(e); // ???
}
}
}
protected abstract void run();
protected final void yield(Object value)
{
synchronized(_lock)
{
_list.add(value);
_lock.notify();
try
{
_lock.wait();
}
catch (InterruptedException e)
{
throw new RuntimeException(e); // ???
}
}
}
private void ready() // must be called in synchronized(_lock)
{
if (!_terminated && _list.isEmpty())
{
_lock.notify();
try
{
_lock.wait();
}
catch (InterruptedException e)
{
throw new RuntimeException(e); // ???
}
}
}
public boolean hasNext()
{
synchronized(_lock)
{
ready();
return !_list.isEmpty();
}
}
public Object next()
{
synchronized(_lock)
{
ready();
if (_list.isEmpty())
{
throw new RuntimeException("EOF");
}
return _list.removeFirst();
}
}
}
//////////////////////////////////////////////////
// Main
class Test extends CoRoutine
{
public int value;
protected void run()
{
while (true)
{
yield(value);
}
}
}
class Main
{
public static void main(String[] args)
{
Test t = new Test();
for (int i = 0; i < 3; ++i)
{
t.value = i;
System.out.println(t.next());
}
}
}