blob: a2713af1a18f165504fb189e0691d87276fd72fa [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:
25 apply(self.func, (self,) + self.args)
26 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:
35 raise TypeError, 'put() called on killed generator'
36 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:
44 raise TypeError, 'get() called on killed generator'
45 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:
53 raise TypeError, 'kill() called on killed generator'
54 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):
Tim Peters68a323c2004-07-18 16:56:37 +000061 k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
62 while 1:
63 # Next approximation
64 p, q, k = k*k, 2L*k+1L, k+1L
65 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))
70 a, a1 = 10L*(a%b), 10L*(a1%b1)
71 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, ())
77 for i in range(10): print g.get(),
78 print
79 h = g.clone()
80 g.kill()
81 while 1:
82 print h.get(),
Guido van Rossum70dc86f1994-05-03 14:15:01 +000083
84test()