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