mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			2 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:
 | |
| 					apply(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()
 | 
