mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
	
	
		
			85 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			85 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() |