| 
									
										
										
										
											1994-05-03 14:15:01 +00:00
										 |  |  | # Generator implementation using threads | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import thread | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Killed = 'Generator.Killed' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Generator: | 
					
						
							| 
									
										
										
										
											2004-07-18 16:56:37 +00:00
										 |  |  |     # 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: | 
					
						
							| 
									
										
										
										
											2006-03-17 08:00:19 +00:00
										 |  |  |                     self.func(self, *self.args) | 
					
						
							| 
									
										
										
										
											2004-07-18 16:56:37 +00:00
										 |  |  |                 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) | 
					
						
							| 
									
										
										
										
											1994-05-03 14:15:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def pi(g): | 
					
						
							| 
									
										
										
										
											2004-07-18 16:56:37 +00:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											1994-05-03 14:15:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def test(): | 
					
						
							| 
									
										
										
										
											2004-07-18 16:56:37 +00:00
										 |  |  |     g = Generator(pi, ()) | 
					
						
							|  |  |  |     g.kill() | 
					
						
							|  |  |  |     g = Generator(pi, ()) | 
					
						
							|  |  |  |     for i in range(10): print g.get(), | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  |     h = g.clone() | 
					
						
							|  |  |  |     g.kill() | 
					
						
							|  |  |  |     while 1: | 
					
						
							|  |  |  |         print h.get(), | 
					
						
							| 
									
										
										
										
											1994-05-03 14:15:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | test() |