symbian-qemu-0.9.1-12/python-2.6.1/Demo/threads/Generator.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 # Generator implementation using threads
       
     2 
       
     3 import sys
       
     4 import thread
       
     5 
       
     6 class Killed(Exception):
       
     7     pass
       
     8 
       
     9 class Generator:
       
    10     # Constructor
       
    11     def __init__(self, func, args):
       
    12         self.getlock = thread.allocate_lock()
       
    13         self.putlock = thread.allocate_lock()
       
    14         self.getlock.acquire()
       
    15         self.putlock.acquire()
       
    16         self.func = func
       
    17         self.args = args
       
    18         self.done = 0
       
    19         self.killed = 0
       
    20         thread.start_new_thread(self._start, ())
       
    21 
       
    22     # Internal routine
       
    23     def _start(self):
       
    24         try:
       
    25             self.putlock.acquire()
       
    26             if not self.killed:
       
    27                 try:
       
    28                     apply(self.func, (self,) + self.args)
       
    29                 except Killed:
       
    30                     pass
       
    31         finally:
       
    32             if not self.killed:
       
    33                 self.done = 1
       
    34                 self.getlock.release()
       
    35 
       
    36     # Called by producer for each value; raise Killed if no more needed
       
    37     def put(self, value):
       
    38         if self.killed:
       
    39             raise TypeError, 'put() called on killed generator'
       
    40         self.value = value
       
    41         self.getlock.release()  # Resume consumer thread
       
    42         self.putlock.acquire()  # Wait for next get() call
       
    43         if self.killed:
       
    44             raise Killed
       
    45 
       
    46     # Called by producer to get next value; raise EOFError if no more
       
    47     def get(self):
       
    48         if self.killed:
       
    49             raise TypeError, 'get() called on killed generator'
       
    50         self.putlock.release()  # Resume producer thread
       
    51         self.getlock.acquire()  # Wait for value to appear
       
    52         if self.done:
       
    53             raise EOFError  # Say there are no more values
       
    54         return self.value
       
    55 
       
    56     # Called by consumer if no more values wanted
       
    57     def kill(self):
       
    58         if self.killed:
       
    59             raise TypeError, 'kill() called on killed generator'
       
    60         self.killed = 1
       
    61         self.putlock.release()
       
    62 
       
    63     # Clone constructor
       
    64     def clone(self):
       
    65         return Generator(self.func, self.args)
       
    66 
       
    67 def pi(g):
       
    68     k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
       
    69     while 1:
       
    70         # Next approximation
       
    71         p, q, k = k*k, 2L*k+1L, k+1L
       
    72         a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
       
    73         # Print common digits
       
    74         d, d1 = a//b, a1//b1
       
    75         while d == d1:
       
    76             g.put(int(d))
       
    77             a, a1 = 10L*(a%b), 10L*(a1%b1)
       
    78             d, d1 = a//b, a1//b1
       
    79 
       
    80 def test():
       
    81     g = Generator(pi, ())
       
    82     g.kill()
       
    83     g = Generator(pi, ())
       
    84     for i in range(10): print g.get(),
       
    85     print
       
    86     h = g.clone()
       
    87     g.kill()
       
    88     while 1:
       
    89         print h.get(),
       
    90         sys.stdout.flush()
       
    91 
       
    92 test()