# Generator implementation using threads | |
import thread | |
Killed = 'Generator.Killed' | |
class Generator: | |
# Constructor | |
def __init__(self, func, args): | |
self.getlock = thread.allocate_lock() | |
self.putlock = thread.allocate_lock() | |
self.getlock.acquire() | |
self.putlock.acquire() | |
self.func = func | |
self.args = args | |
self.done = 0 | |
self.killed = 0 | |
thread.start_new_thread(self._start, ()) | |
# Internal routine | |
def _start(self): | |
try: | |
self.putlock.acquire() | |
if not self.killed: | |
try: | |
apply(self.func, (self,) + self.args) | |
except Killed: | |
pass | |
finally: | |
if not self.killed: | |
self.done = 1 | |
self.getlock.release() | |
# Called by producer for each value; raise Killed if no more needed | |
def put(self, value): | |
if self.killed: | |
raise TypeError, 'put() called on killed generator' | |
self.value = value | |
self.getlock.release() # Resume consumer thread | |
self.putlock.acquire() # Wait for next get() call | |
if self.killed: | |
raise Killed | |
# Called by producer to get next value; raise EOFError if no more | |
def get(self): | |
if self.killed: | |
raise TypeError, 'get() called on killed generator' | |
self.putlock.release() # Resume producer thread | |
self.getlock.acquire() # Wait for value to appear | |
if self.done: | |
raise EOFError # Say there are no more values | |
return self.value | |
# Called by consumer if no more values wanted | |
def kill(self): | |
if self.killed: | |
raise TypeError, 'kill() called on killed generator' | |
self.killed = 1 | |
self.putlock.release() | |
# Clone constructor | |
def clone(self): | |
return Generator(self.func, self.args) | |
def pi(g): | |
k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L | |
while 1: | |
# Next approximation | |
p, q, k = k*k, 2L*k+1L, k+1L | |
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 | |
# Print common digits | |
d, d1 = a/b, a1/b1 | |
while d == d1: | |
g.put(int(d)) | |
a, a1 = 10L*(a%b), 10L*(a1%b1) | |
d, d1 = a/b, a1/b1 | |
def test(): | |
g = Generator(pi, ()) | |
g.kill() | |
g = Generator(pi, ()) | |
for i in range(10): print g.get(), | |
h = g.clone() | |
g.kill() | |
while 1: | |
print h.get(), | |
test() |