mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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:
 | |
|                     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(),
 | |
|     print
 | |
|     h = g.clone()
 | |
|     g.kill()
 | |
|     while 1:
 | |
|         print h.get(),
 | |
| 
 | |
| test()
 | 
