blob: 0cc1bda34805e561949cf4fd8f1ce9d0599e44c2 [file] [log] [blame]
Guido van Rossum70dc86f1994-05-03 14:15:01 +00001# Generator implementation using threads
2
3import thread
4
5Killed = 'Generator.Killed'
6
7class Generator:
Tim Peters68a323c2004-07-18 16:56:37 +00008 # Constructor
9 def __init__(self, func, args):
10 self.getlock = thread.allocate_lock()
11 self.putlock = thread.allocate_lock()
12 self.getlock.acquire()
13 self.putlock.acquire()
14 self.func = func
15 self.args = args
16 self.done = 0
17 self.killed = 0
18 thread.start_new_thread(self._start, ())
19 # Internal routine
20 def _start(self):
21 try:
22 self.putlock.acquire()
23 if not self.killed:
24 try:
Neal Norwitzd9108552006-03-17 08:00:19 +000025 self.func(self, *self.args)
Tim Peters68a323c2004-07-18 16:56:37 +000026 except Killed:
27 pass
28 finally:
29 if not self.killed:
30 self.done = 1
31 self.getlock.release()
32 # Called by producer for each value; raise Killed if no more needed
33 def put(self, value):
34 if self.killed:
Collin Winter6f2df4d2007-07-17 20:59:35 +000035 raise TypeError('put() called on killed generator')
Tim Peters68a323c2004-07-18 16:56:37 +000036 self.value = value
37 self.getlock.release() # Resume consumer thread
38 self.putlock.acquire() # Wait for next get() call
39 if self.killed:
40 raise Killed
41 # Called by producer to get next value; raise EOFError if no more
42 def get(self):
43 if self.killed:
Collin Winter6f2df4d2007-07-17 20:59:35 +000044 raise TypeError('get() called on killed generator')
Tim Peters68a323c2004-07-18 16:56:37 +000045 self.putlock.release() # Resume producer thread
46 self.getlock.acquire() # Wait for value to appear
47 if self.done:
48 raise EOFError # Say there are no more values
49 return self.value
50 # Called by consumer if no more values wanted
51 def kill(self):
52 if self.killed:
Collin Winter6f2df4d2007-07-17 20:59:35 +000053 raise TypeError('kill() called on killed generator')
Tim Peters68a323c2004-07-18 16:56:37 +000054 self.killed = 1
55 self.putlock.release()
56 # Clone constructor
57 def clone(self):
58 return Generator(self.func, self.args)
Guido van Rossum70dc86f1994-05-03 14:15:01 +000059
60def pi(g):
Collin Winter6f2df4d2007-07-17 20:59:35 +000061 k, a, b, a1, b1 = 2, 4, 1, 12, 4
Tim Peters68a323c2004-07-18 16:56:37 +000062 while 1:
63 # Next approximation
Collin Winter6f2df4d2007-07-17 20:59:35 +000064 p, q, k = k*k, 2*k+1, k+1
Tim Peters68a323c2004-07-18 16:56:37 +000065 a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
66 # Print common digits
67 d, d1 = a/b, a1/b1
68 while d == d1:
69 g.put(int(d))
Collin Winter6f2df4d2007-07-17 20:59:35 +000070 a, a1 = 10*(a%b), 10*(a1%b1)
Tim Peters68a323c2004-07-18 16:56:37 +000071 d, d1 = a/b, a1/b1
Guido van Rossum70dc86f1994-05-03 14:15:01 +000072
73def test():
Tim Peters68a323c2004-07-18 16:56:37 +000074 g = Generator(pi, ())
75 g.kill()
76 g = Generator(pi, ())
Collin Winter6f2df4d2007-07-17 20:59:35 +000077 for i in range(10): print(g.get(), end=' ')
78 print()
Tim Peters68a323c2004-07-18 16:56:37 +000079 h = g.clone()
80 g.kill()
81 while 1:
Collin Winter6f2df4d2007-07-17 20:59:35 +000082 print(h.get(), end=' ')
Guido van Rossum70dc86f1994-05-03 14:15:01 +000083
84test()