mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +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()
 |