source file: /System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/threading.py
file stats: 529 lines, 167 executed: 31.6% covered
   1. """Thread module emulating a subset of Java's threading model."""
   2. 
   3. import sys as _sys
   4. 
   5. try:
   6.     import thread
   7. except ImportError:
   8.     del _sys.modules[__name__]
   9.     raise
  10. 
  11. from StringIO import StringIO as _StringIO
  12. from time import time as _time, sleep as _sleep
  13. from traceback import print_exc as _print_exc
  14. 
  15. # Rename some stuff so "from threading import *" is safe
  16. __all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
  17.            'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
  18.            'Timer', 'setprofile', 'settrace']
  19. 
  20. _start_new_thread = thread.start_new_thread
  21. _allocate_lock = thread.allocate_lock
  22. _get_ident = thread.get_ident
  23. ThreadError = thread.error
  24. del thread
  25. 
  26. 
  27. # Debug support (adapted from ihooks.py).
  28. # All the major classes here derive from _Verbose.  We force that to
  29. # be a new-style class so that all the major classes here are new-style.
  30. # This helps debugging (type(instance) is more revealing for instances
  31. # of new-style classes).
  32. 
  33. _VERBOSE = False
  34. 
  35. if __debug__:
  36. 
  37.     class _Verbose(object):
  38. 
  39.         def __init__(self, verbose=None):
  40.             if verbose is None:
  41.                 verbose = _VERBOSE
  42.             self.__verbose = verbose
  43. 
  44.         def _note(self, format, *args):
  45.             if self.__verbose:
  46.                 format = format % args
  47.                 format = "%s: %s\n" % (
  48.                     currentThread().getName(), format)
  49.                 _sys.stderr.write(format)
  50. 
  51. else:
  52.     # Disable this when using "python -O"
  53.     class _Verbose(object):
  54.         def __init__(self, verbose=None):
  55.             pass
  56.         def _note(self, *args):
  57.             pass
  58. 
  59. # Support for profile and trace hooks
  60. 
  61. _profile_hook = None
  62. _trace_hook = None
  63. 
  64. def setprofile(func):
  65.     global _profile_hook
  66.     _profile_hook = func
  67. 
  68. def settrace(func):
  69.     global _trace_hook
  70.     _trace_hook = func
  71. 
  72. # Synchronization classes
  73. 
  74. Lock = _allocate_lock
  75. 
  76. def RLock(*args, **kwargs):
  77.     return _RLock(*args, **kwargs)
  78. 
  79. class _RLock(_Verbose):
  80. 
  81.     def __init__(self, verbose=None):
  82.         _Verbose.__init__(self, verbose)
  83.         self.__block = _allocate_lock()
  84.         self.__owner = None
  85.         self.__count = 0
  86. 
  87.     def __repr__(self):
  88.         return "<%s(%s, %d)>" % (
  89.                 self.__class__.__name__,
  90.                 self.__owner and self.__owner.getName(),
  91.                 self.__count)
  92. 
  93.     def acquire(self, blocking=1):
  94.         me = currentThread()
  95.         if self.__owner is me:
  96.             self.__count = self.__count + 1
  97.             if __debug__:
  98.                 self._note("%s.acquire(%s): recursive success", self, blocking)
  99.             return 1
 100.         rc = self.__block.acquire(blocking)
 101.         if rc:
 102.             self.__owner = me
 103.             self.__count = 1
 104.             if __debug__:
 105.                 self._note("%s.acquire(%s): initial success", self, blocking)
 106.         else:
 107.             if __debug__:
 108.                 self._note("%s.acquire(%s): failure", self, blocking)
 109.         return rc
 110. 
 111.     def release(self):
 112.         me = currentThread()
 113.         assert self.__owner is me, "release() of un-acquire()d lock"
 114.         self.__count = count = self.__count - 1
 115.         if not count:
 116.             self.__owner = None
 117.             self.__block.release()
 118.             if __debug__:
 119.                 self._note("%s.release(): final release", self)
 120.         else:
 121.             if __debug__:
 122.                 self._note("%s.release(): non-final release", self)
 123. 
 124.     # Internal methods used by condition variables
 125. 
 126.     def _acquire_restore(self, (count, owner)):
 127.         self.__block.acquire()
 128.         self.__count = count
 129.         self.__owner = owner
 130.         if __debug__:
 131.             self._note("%s._acquire_restore()", self)
 132. 
 133.     def _release_save(self):
 134.         if __debug__:
 135.             self._note("%s._release_save()", self)
 136.         count = self.__count
 137.         self.__count = 0
 138.         owner = self.__owner
 139.         self.__owner = None
 140.         self.__block.release()
 141.         return (count, owner)
 142. 
 143.     def _is_owned(self):
 144.         return self.__owner is currentThread()
 145. 
 146. 
 147. def Condition(*args, **kwargs):
 148.     return _Condition(*args, **kwargs)
 149. 
 150. class _Condition(_Verbose):
 151. 
 152.     def __init__(self, lock=None, verbose=None):
 153.         _Verbose.__init__(self, verbose)
 154.         if lock is None:
 155.             lock = RLock()
 156.         self.__lock = lock
 157.         # Export the lock's acquire() and release() methods
 158.         self.acquire = lock.acquire
 159.         self.release = lock.release
 160.         # If the lock defines _release_save() and/or _acquire_restore(),
 161.         # these override the default implementations (which just call
 162.         # release() and acquire() on the lock).  Ditto for _is_owned().
 163.         try:
 164.             self._release_save = lock._release_save
 165.         except AttributeError:
 166.             pass
 167.         try:
 168.             self._acquire_restore = lock._acquire_restore
 169.         except AttributeError:
 170.             pass
 171.         try:
 172.             self._is_owned = lock._is_owned
 173.         except AttributeError:
 174.             pass
 175.         self.__waiters = []
 176. 
 177.     def __repr__(self):
 178.         return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters))
 179. 
 180.     def _release_save(self):
 181.         self.__lock.release()           # No state to save
 182. 
 183.     def _acquire_restore(self, x):
 184.         self.__lock.acquire()           # Ignore saved state
 185. 
 186.     def _is_owned(self):
 187.         # Return True if lock is owned by currentThread.
 188.         # This method is called only if __lock doesn't have _is_owned().
 189.         if self.__lock.acquire(0):
 190.             self.__lock.release()
 191.             return False
 192.         else:
 193.             return True
 194. 
 195.     def wait(self, timeout=None):
 196.         assert self._is_owned(), "wait() of un-acquire()d lock"
 197.         waiter = _allocate_lock()
 198.         waiter.acquire()
 199.         self.__waiters.append(waiter)
 200.         saved_state = self._release_save()
 201.         try:    # restore state no matter what (e.g., KeyboardInterrupt)
 202.             if timeout is None:
 203.                 waiter.acquire()
 204.                 if __debug__:
 205.                     self._note("%s.wait(): got it", self)
 206.             else:
 207.                 # Balancing act:  We can't afford a pure busy loop, so we
 208.                 # have to sleep; but if we sleep the whole timeout time,
 209.                 # we'll be unresponsive.  The scheme here sleeps very
 210.                 # little at first, longer as time goes on, but never longer
 211.                 # than 20 times per second (or the timeout time remaining).
 212.                 endtime = _time() + timeout
 213.                 delay = 0.0005 # 500 us -> initial delay of 1 ms
 214.                 while True:
 215.                     gotit = waiter.acquire(0)
 216.                     if gotit:
 217.                         break
 218.                     remaining = endtime - _time()
 219.                     if remaining <= 0:
 220.                         break
 221.                     delay = min(delay * 2, remaining, .05)
 222.                     _sleep(delay)
 223.                 if not gotit:
 224.                     if __debug__:
 225.                         self._note("%s.wait(%s): timed out", self, timeout)
 226.                     try:
 227.                         self.__waiters.remove(waiter)
 228.                     except ValueError:
 229.                         pass
 230.                 else:
 231.                     if __debug__:
 232.                         self._note("%s.wait(%s): got it", self, timeout)
 233.         finally:
 234.             self._acquire_restore(saved_state)
 235. 
 236.     def notify(self, n=1):
 237.         assert self._is_owned(), "notify() of un-acquire()d lock"
 238.         __waiters = self.__waiters
 239.         waiters = __waiters[:n]
 240.         if not waiters:
 241.             if __debug__:
 242.                 self._note("%s.notify(): no waiters", self)
 243.             return
 244.         self._note("%s.notify(): notifying %d waiter%s", self, n,
 245.                    n!=1 and "s" or "")
 246.         for waiter in waiters:
 247.             waiter.release()
 248.             try:
 249.                 __waiters.remove(waiter)
 250.             except ValueError:
 251.                 pass
 252. 
 253.     def notifyAll(self):
 254.         self.notify(len(self.__waiters))
 255. 
 256. 
 257. def Semaphore(*args, **kwargs):
 258.     return _Semaphore(*args, **kwargs)
 259. 
 260. class _Semaphore(_Verbose):
 261. 
 262.     # After Tim Peters' semaphore class, but not quite the same (no maximum)
 263. 
 264.     def __init__(self, value=1, verbose=None):
 265.         assert value >= 0, "Semaphore initial value must be >= 0"
 266.         _Verbose.__init__(self, verbose)
 267.         self.__cond = Condition(Lock())
 268.         self.__value = value
 269. 
 270.     def acquire(self, blocking=1):
 271.         rc = False
 272.         self.__cond.acquire()
 273.         while self.__value == 0:
 274.             if not blocking:
 275.                 break
 276.             if __debug__:
 277.                 self._note("%s.acquire(%s): blocked waiting, value=%s",
 278.                            self, blocking, self.__value)
 279.             self.__cond.wait()
 280.         else:
 281.             self.__value = self.__value - 1
 282.             if __debug__:
 283.                 self._note("%s.acquire: success, value=%s",
 284.                            self, self.__value)
 285.             rc = True
 286.         self.__cond.release()
 287.         return rc
 288. 
 289.     def release(self):
 290.         self.__cond.acquire()
 291.         self.__value = self.__value + 1
 292.         if __debug__:
 293.             self._note("%s.release: success, value=%s",
 294.                        self, self.__value)
 295.         self.__cond.notify()
 296.         self.__cond.release()
 297. 
 298. 
 299. def BoundedSemaphore(*args, **kwargs):
 300.     return _BoundedSemaphore(*args, **kwargs)
 301. 
 302. class _BoundedSemaphore(_Semaphore):
 303.     """Semaphore that checks that # releases is <= # acquires"""
 304.     def __init__(self, value=1, verbose=None):
 305.         _Semaphore.__init__(self, value, verbose)
 306.         self._initial_value = value
 307. 
 308.     def release(self):
 309.         if self._Semaphore__value >= self._initial_value:
 310.             raise ValueError, "Semaphore released too many times"
 311.         return _Semaphore.release(self)
 312. 
 313. 
 314. def Event(*args, **kwargs):
 315.     return _Event(*args, **kwargs)
 316. 
 317. class _Event(_Verbose):
 318. 
 319.     # After Tim Peters' event class (without is_posted())
 320. 
 321.     def __init__(self, verbose=None):
 322.         _Verbose.__init__(self, verbose)
 323.         self.__cond = Condition(Lock())
 324.         self.__flag = False
 325. 
 326.     def isSet(self):
 327.         return self.__flag
 328. 
 329.     def set(self):
 330.         self.__cond.acquire()
 331.         try:
 332.             self.__flag = True
 333.             self.__cond.notifyAll()
 334.         finally:
 335.             self.__cond.release()
 336. 
 337.     def clear(self):
 338.         self.__cond.acquire()
 339.         try:
 340.             self.__flag = False
 341.         finally:
 342.             self.__cond.release()
 343. 
 344.     def wait(self, timeout=None):
 345.         self.__cond.acquire()
 346.         try:
 347.             if not self.__flag:
 348.                 self.__cond.wait(timeout)
 349.         finally:
 350.             self.__cond.release()
 351. 
 352. # Helper to generate new thread names
 353. _counter = 0
 354. def _newname(template="Thread-%d"):
 355.     global _counter
 356.     _counter = _counter + 1
 357.     return template % _counter
 358. 
 359. # Active thread administration
 360. _active_limbo_lock = _allocate_lock()
 361. _active = {}
 362. _limbo = {}
 363. 
 364. 
 365. # Main class for threads
 366. 
 367. class Thread(_Verbose):
 368. 
 369.     __initialized = False
 370.     # Need to store a reference to sys.exc_info for printing
 371.     # out exceptions when a thread tries to accept a global during interp.
 372.     # shutdown and thus raises an exception about trying to perform some
 373.     # operation on/with a NoneType
 374.     __exc_info = _sys.exc_info
 375. 
 376.     def __init__(self, group=None, target=None, name=None,
 377.                  args=(), kwargs={}, verbose=None):
 378.         assert group is None, "group argument must be None for now"
 379.         _Verbose.__init__(self, verbose)
 380.         self.__target = target
 381.         self.__name = str(name or _newname())
 382.         self.__args = args
 383.         self.__kwargs = kwargs
 384.         self.__daemonic = self._set_daemon()
 385.         self.__started = False
 386.         self.__stopped = False
 387.         self.__block = Condition(Lock())
 388.         self.__initialized = True
 389.         # sys.stderr is not stored in the class like
 390.         # sys.exc_info since it can be changed during execution
 391.         self.__stderr = _sys.stderr
 392. 
 393.     def _set_daemon(self):
 394.         # Overridden in _MainThread and _DummyThread
 395.         return currentThread().isDaemon()
 396. 
 397.     def __repr__(self):
 398.         assert self.__initialized, "Thread.__init__() was not called"
 399.         status = "initial"
 400.         if self.__started:
 401.             status = "started"
 402.         if self.__stopped:
 403.             status = "stopped"
 404.         if self.__daemonic:
 405.             status = status + " daemon"
 406.         return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status)
 407. 
 408.     def start(self):
 409.         assert self.__initialized, "Thread.__init__() not called"
 410.         assert not self.__started, "thread already started"
 411.         if __debug__:
 412.             self._note("%s.start(): starting thread", self)
 413.         _active_limbo_lock.acquire()
 414.         _limbo[self] = self
 415.         _active_limbo_lock.release()
 416.         _start_new_thread(self.__bootstrap, ())
 417.         self.__started = True
 418.         _sleep(0.000001)    # 1 usec, to let the thread run (Solaris hack)
 419. 
 420.     def run(self):
 421.         if self.__target:
 422.             self.__target(*self.__args, **self.__kwargs)
 423. 
 424.     def __bootstrap(self):
 425.         try:
 426.             self.__started = True
 427.             _active_limbo_lock.acquire()
 428.             _active[_get_ident()] = self
 429.             del _limbo[self]
 430.             _active_limbo_lock.release()
 431.             if __debug__:
 432.                 self._note("%s.__bootstrap(): thread started", self)
 433. 
 434.             if _trace_hook:
 435.                 self._note("%s.__bootstrap(): registering trace hook", self)
 436.                 _sys.settrace(_trace_hook)
 437.             if _profile_hook:
 438.                 self._note("%s.__bootstrap(): registering profile hook", self)
 439.                 _sys.setprofile(_profile_hook)
 440. 
 441.             try:
 442.                 self.run()
 443.             except SystemExit:
 444.                 if __debug__:
 445.                     self._note("%s.__bootstrap(): raised SystemExit", self)
 446.             except:
 447.                 if __debug__:
 448.                     self._note("%s.__bootstrap(): unhandled exception", self)
 449.                 # If sys.stderr is no more (most likely from interpreter
 450.                 # shutdown) use self.__stderr.  Otherwise still use sys (as in
 451.                 # _sys) in case sys.stderr was redefined.
 452.                 if _sys:
 453.                     _sys.stderr.write("Exception in thread %s:" %
 454.                             self.getName())
 455.                     _print_exc(file=_sys.stderr)
 456.                 else:
 457.                     # Do the best job possible w/o a huge amt. of code to
 458.                     # approx. a traceback stack trace
 459.                     exc_type, exc_value, exc_tb = self.__exc_info()
 460.                     try:
 461.                         print>>self.__stderr, (
 462.                             "Exception in thread " + self.getName() +
 463.                             " (most likely raised during interpreter shutdown):")
 464.                         print>>self.__stderr, (
 465.                             "Traceback (most recent call last):")
 466.                         while exc_tb:
 467.                             print>>self.__stderr, (
 468.                                 '  File "%s", line %s, in %s' %
 469.                                 (exc_tb.tb_frame.f_code.co_filename,
 470.                                     exc_tb.tb_lineno,
 471.                                     exc_tb.tb_frame.f_code.co_name))
 472.                             exc_tb = exc_tb.tb_next
 473.                         print>>self.__stderr, ("%s: %s" % (exc_type, exc_value))
 474.                     # Make sure that exc_tb gets deleted since it is a memory
 475.                     # hog; deleting everything else is just for thoroughness
 476.                     finally:
 477.                         del exc_type, exc_value, exc_tb
 478.             else:
 479.                 if __debug__:
 480.                     self._note("%s.__bootstrap(): normal return", self)
 481.         finally:
 482.             self.__stop()
 483.             try:
 484.                 self.__delete()
 485.             except:
 486.                 pass
 487. 
 488.     def __stop(self):
 489.         self.__block.acquire()
 490.         self.__stopped = True
 491.         self.__block.notifyAll()
 492.         self.__block.release()
 493. 
 494.     def __delete(self):
 495.         "Remove current thread from the dict of currently running threads."
 496. 
 497.         # Notes about running with dummy_thread:
 498.         #
 499.         # Must take care to not raise an exception if dummy_thread is being
 500.         # used (and thus this module is being used as an instance of
 501.         # dummy_threading).  dummy_thread.get_ident() always returns -1 since
 502.         # there is only one thread if dummy_thread is being used.  Thus
 503.         # len(_active) is always <= 1 here, and any Thread instance created
 504.         # overwrites the (if any) thread currently registered in _active.
 505.         #
 506.         # An instance of _MainThread is always created by 'threading'.  This
 507.         # gets overwritten the instant an instance of Thread is created; both
 508.         # threads return -1 from dummy_thread.get_ident() and thus have the
 509.         # same key in the dict.  So when the _MainThread instance created by
 510.         # 'threading' tries to clean itself up when atexit calls this method
 511.         # it gets a KeyError if another Thread instance was created.
 512.         #
 513.         # This all means that KeyError from trying to delete something from
 514.         # _active if dummy_threading is being used is a red herring.  But
 515.         # since it isn't if dummy_threading is *not* being used then don't
 516.         # hide the exception.
 517. 
 518.         _active_limbo_lock.acquire()
 519.         try:
 520.             try:
 521.                 del _active[_get_ident()]
 522.             except KeyError:
 523.                 if 'dummy_threading' not in _sys.modules:
 524.                     raise
 525.         finally:
 526.             _active_limbo_lock.release()
 527. 
 528.     def join(self, timeout=None):
 529.         assert self.__initialized, "Thread.__init__() not called"
 530.         assert self.__started, "cannot join thread before it is started"
 531.         assert self is not currentThread(), "cannot join current thread"
 532.         if __debug__:
 533.             if not self.__stopped:
 534.                 self._note("%s.join(): waiting until thread stops", self)
 535.         self.__block.acquire()
 536.         if timeout is None:
 537.             while not self.__stopped:
 538.                 self.__block.wait()
 539.             if __debug__:
 540.                 self._note("%s.join(): thread stopped", self)
 541.         else:
 542.             deadline = _time() + timeout
 543.             while not self.__stopped:
 544.                 delay = deadline - _time()
 545.                 if delay <= 0:
 546.                     if __debug__:
 547.                         self._note("%s.join(): timed out", self)
 548.                     break
 549.                 self.__block.wait(delay)
 550.             else:
 551.                 if __debug__:
 552.                     self._note("%s.join(): thread stopped", self)
 553.         self.__block.release()
 554. 
 555.     def getName(self):
 556.         assert self.__initialized, "Thread.__init__() not called"
 557.         return self.__name
 558. 
 559.     def setName(self, name):
 560.         assert self.__initialized, "Thread.__init__() not called"
 561.         self.__name = str(name)
 562. 
 563.     def isAlive(self):
 564.         assert self.__initialized, "Thread.__init__() not called"
 565.         return self.__started and not self.__stopped
 566. 
 567.     def isDaemon(self):
 568.         assert self.__initialized, "Thread.__init__() not called"
 569.         return self.__daemonic
 570. 
 571.     def setDaemon(self, daemonic):
 572.         assert self.__initialized, "Thread.__init__() not called"
 573.         assert not self.__started, "cannot set daemon status of active thread"
 574.         self.__daemonic = daemonic
 575. 
 576. # The timer class was contributed by Itamar Shtull-Trauring
 577. 
 578. def Timer(*args, **kwargs):
 579.     return _Timer(*args, **kwargs)
 580. 
 581. class _Timer(Thread):
 582.     """Call a function after a specified number of seconds:
 583. 
 584.     t = Timer(30.0, f, args=[], kwargs={})
 585.     t.start()
 586.     t.cancel() # stop the timer's action if it's still waiting
 587.     """
 588. 
 589.     def __init__(self, interval, function, args=[], kwargs={}):
 590.         Thread.__init__(self)
 591.         self.interval = interval
 592.         self.function = function
 593.         self.args = args
 594.         self.kwargs = kwargs
 595.         self.finished = Event()
 596. 
 597.     def cancel(self):
 598.         """Stop the timer if it hasn't finished yet"""
 599.         self.finished.set()
 600. 
 601.     def run(self):
 602.         self.finished.wait(self.interval)
 603.         if not self.finished.isSet():
 604.             self.function(*self.args, **self.kwargs)
 605.         self.finished.set()
 606. 
 607. # Special thread class to represent the main thread
 608. # This is garbage collected through an exit handler
 609. 
 610. class _MainThread(Thread):
 611. 
 612.     def __init__(self):
 613.         Thread.__init__(self, name="MainThread")
 614.         self._Thread__started = True
 615.         _active_limbo_lock.acquire()
 616.         _active[_get_ident()] = self
 617.         _active_limbo_lock.release()
 618.         import atexit
 619.         atexit.register(self.__exitfunc)
 620. 
 621.     def _set_daemon(self):
 622.         return False
 623. 
 624.     def __exitfunc(self):
 625.         self._Thread__stop()
 626.         t = _pickSomeNonDaemonThread()
 627.         if t:
 628.             if __debug__:
 629.                 self._note("%s: waiting for other threads", self)
 630.         while t:
 631.             t.join()
 632.             t = _pickSomeNonDaemonThread()
 633.         if __debug__:
 634.             self._note("%s: exiting", self)
 635.         self._Thread__delete()
 636. 
 637. def _pickSomeNonDaemonThread():
 638.     for t in enumerate():
 639.         if not t.isDaemon() and t.isAlive():
 640.             return t
 641.     return None
 642. 
 643. 
 644. # Dummy thread class to represent threads not started here.
 645. # These aren't garbage collected when they die,
 646. # nor can they be waited for.
 647. # Their purpose is to return *something* from currentThread().
 648. # They are marked as daemon threads so we won't wait for them
 649. # when we exit (conform previous semantics).
 650. 
 651. class _DummyThread(Thread):
 652. 
 653.     def __init__(self):
 654.         Thread.__init__(self, name=_newname("Dummy-%d"))
 655.         self._Thread__started = True
 656.         _active_limbo_lock.acquire()
 657.         _active[_get_ident()] = self
 658.         _active_limbo_lock.release()
 659. 
 660.     def _set_daemon(self):
 661.         return True
 662. 
 663.     def join(self, timeout=None):
 664.         assert False, "cannot join a dummy thread"
 665. 
 666. 
 667. # Global API functions
 668. 
 669. def currentThread():
 670.     try:
 671.         return _active[_get_ident()]
 672.     except KeyError:
 673.         ##print "currentThread(): no current thread for", _get_ident()
 674.         return _DummyThread()
 675. 
 676. def activeCount():
 677.     _active_limbo_lock.acquire()
 678.     count = len(_active) + len(_limbo)
 679.     _active_limbo_lock.release()
 680.     return count
 681. 
 682. def enumerate():
 683.     _active_limbo_lock.acquire()
 684.     active = _active.values() + _limbo.values()
 685.     _active_limbo_lock.release()
 686.     return active
 687. 
 688. # Create the main thread object
 689. 
 690. _MainThread()
 691. 
 692. 
 693. # Self-test code
 694. 
 695. def _test():
 696. 
 697.     class BoundedQueue(_Verbose):
 698. 
 699.         def __init__(self, limit):
 700.             _Verbose.__init__(self)
 701.             self.mon = RLock()
 702.             self.rc = Condition(self.mon)
 703.             self.wc = Condition(self.mon)
 704.             self.limit = limit
 705.             self.queue = []
 706. 
 707.         def put(self, item):
 708.             self.mon.acquire()
 709.             while len(self.queue) >= self.limit:
 710.                 self._note("put(%s): queue full", item)
 711.                 self.wc.wait()
 712.             self.queue.append(item)
 713.             self._note("put(%s): appended, length now %d",
 714.                        item, len(self.queue))
 715.             self.rc.notify()
 716.             self.mon.release()
 717. 
 718.         def get(self):
 719.             self.mon.acquire()
 720.             while not self.queue:
 721.                 self._note("get(): queue empty")
 722.                 self.rc.wait()
 723.             item = self.queue.pop(0)
 724.             self._note("get(): got %s, %d left", item, len(self.queue))
 725.             self.wc.notify()
 726.             self.mon.release()
 727.             return item
 728. 
 729.     class ProducerThread(Thread):
 730. 
 731.         def __init__(self, queue, quota):
 732.             Thread.__init__(self, name="Producer")
 733.             self.queue = queue
 734.             self.quota = quota
 735. 
 736.         def run(self):
 737.             from random import random
 738.             counter = 0
 739.             while counter < self.quota:
 740.                 counter = counter + 1
 741.                 self.queue.put("%s.%d" % (self.getName(), counter))
 742.                 _sleep(random() * 0.00001)
 743. 
 744. 
 745.     class ConsumerThread(Thread):
 746. 
 747.         def __init__(self, queue, count):
 748.             Thread.__init__(self, name="Consumer")
 749.             self.queue = queue
 750.             self.count = count
 751. 
 752.         def run(self):
 753.             while self.count > 0:
 754.                 item = self.queue.get()
 755.                 print item
 756.                 self.count = self.count - 1
 757. 
 758.     NP = 3
 759.     QL = 4
 760.     NI = 5
 761. 
 762.     Q = BoundedQueue(QL)
 763.     P = []
 764.     for i in range(NP):
 765.         t = ProducerThread(Q, NI)
 766.         t.setName("Producer-%d" % (i+1))
 767.         P.append(t)
 768.     C = ConsumerThread(Q, NI*NP)
 769.     for t in P:
 770.         t.start()
 771.         _sleep(0.000001)
 772.     C.start()
 773.     for t in P:
 774.         t.join()
 775.     C.join()
 776. 
 777. if __name__ == '__main__':
 778.     _test()