1# Generator implementation using threads 2 3import sys 4import thread 5 6class Killed(Exception): 7 pass 8 9class Generator: 10 # Constructor 11 def __init__(self, func, args): 12 self.getlock = thread.allocate_lock() 13 self.putlock = thread.allocate_lock() 14 self.getlock.acquire() 15 self.putlock.acquire() 16 self.func = func 17 self.args = args 18 self.done = 0 19 self.killed = 0 20 thread.start_new_thread(self._start, ()) 21 22 # Internal routine 23 def _start(self): 24 try: 25 self.putlock.acquire() 26 if not self.killed: 27 try: 28 apply(self.func, (self,) + self.args) 29 except Killed: 30 pass 31 finally: 32 if not self.killed: 33 self.done = 1 34 self.getlock.release() 35 36 # Called by producer for each value; raise Killed if no more needed 37 def put(self, value): 38 if self.killed: 39 raise TypeError, 'put() called on killed generator' 40 self.value = value 41 self.getlock.release() # Resume consumer thread 42 self.putlock.acquire() # Wait for next get() call 43 if self.killed: 44 raise Killed 45 46 # Called by producer to get next value; raise EOFError if no more 47 def get(self): 48 if self.killed: 49 raise TypeError, 'get() called on killed generator' 50 self.putlock.release() # Resume producer thread 51 self.getlock.acquire() # Wait for value to appear 52 if self.done: 53 raise EOFError # Say there are no more values 54 return self.value 55 56 # Called by consumer if no more values wanted 57 def kill(self): 58 if self.killed: 59 raise TypeError, 'kill() called on killed generator' 60 self.killed = 1 61 self.putlock.release() 62 63 # Clone constructor 64 def clone(self): 65 return Generator(self.func, self.args) 66 67def pi(g): 68 k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L 69 while 1: 70 # Next approximation 71 p, q, k = k*k, 2L*k+1L, k+1L 72 a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 73 # Print common digits 74 d, d1 = a//b, a1//b1 75 while d == d1: 76 g.put(int(d)) 77 a, a1 = 10L*(a%b), 10L*(a1%b1) 78 d, d1 = a//b, a1//b1 79 80def test(): 81 g = Generator(pi, ()) 82 g.kill() 83 g = Generator(pi, ()) 84 for i in range(10): print g.get(), 85 print 86 h = g.clone() 87 g.kill() 88 while 1: 89 print h.get(), 90 sys.stdout.flush() 91 92test() 93