home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Bureautique / OpenOffice / Apache_OpenOffice_4.1.1_Win_x86_install_fr.exe / openoffice1.cab / synchronize.py < prev    next >
Text File  |  2014-07-29  |  11KB  |  345 lines

  1. #
  2. # Module implementing synchronization primitives
  3. #
  4. # multiprocessing/synchronize.py
  5. #
  6. # Copyright (c) 2006-2008, R Oudkerk
  7. # All rights reserved.
  8. #
  9. # Redistribution and use in source and binary forms, with or without
  10. # modification, are permitted provided that the following conditions
  11. # are met:
  12. #
  13. # 1. Redistributions of source code must retain the above copyright
  14. #    notice, this list of conditions and the following disclaimer.
  15. # 2. Redistributions in binary form must reproduce the above copyright
  16. #    notice, this list of conditions and the following disclaimer in the
  17. #    documentation and/or other materials provided with the distribution.
  18. # 3. Neither the name of author nor the names of any contributors may be
  19. #    used to endorse or promote products derived from this software
  20. #    without specific prior written permission.
  21. #
  22. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
  23. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  26. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. # SUCH DAMAGE.
  33. #
  34.  
  35. __all__ = [
  36.     'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', 'Event'
  37.     ]
  38.  
  39. import threading
  40. import os
  41. import sys
  42.  
  43. from time import time as _time, sleep as _sleep
  44.  
  45. import _multiprocessing
  46. from multiprocessing.process import current_process
  47. from multiprocessing.util import Finalize, register_after_fork, debug
  48. from multiprocessing.forking import assert_spawning, Popen
  49.  
  50. # Try to import the mp.synchronize module cleanly, if it fails
  51. # raise ImportError for platforms lacking a working sem_open implementation.
  52. # See issue 3770
  53. try:
  54.     from _multiprocessing import SemLock
  55. except (ImportError):
  56.     raise ImportError("This platform lacks a functioning sem_open" +
  57.                       " implementation, therefore, the required" +
  58.                       " synchronization primitives needed will not" +
  59.                       " function, see issue 3770.")
  60.  
  61. #
  62. # Constants
  63. #
  64.  
  65. RECURSIVE_MUTEX, SEMAPHORE = range(2)
  66. SEM_VALUE_MAX = _multiprocessing.SemLock.SEM_VALUE_MAX
  67.  
  68. #
  69. # Base class for semaphores and mutexes; wraps `_multiprocessing.SemLock`
  70. #
  71.  
  72. class SemLock(object):
  73.  
  74.     def __init__(self, kind, value, maxvalue):
  75.         sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
  76.         debug('created semlock with handle %s' % sl.handle)
  77.         self._make_methods()
  78.  
  79.         if sys.platform != 'win32':
  80.             def _after_fork(obj):
  81.                 obj._semlock._after_fork()
  82.             register_after_fork(self, _after_fork)
  83.  
  84.     def _make_methods(self):
  85.         self.acquire = self._semlock.acquire
  86.         self.release = self._semlock.release
  87.  
  88.     def __enter__(self):
  89.         return self._semlock.__enter__()
  90.  
  91.     def __exit__(self, *args):
  92.         return self._semlock.__exit__(*args)
  93.  
  94.     def __getstate__(self):
  95.         assert_spawning(self)
  96.         sl = self._semlock
  97.         return (Popen.duplicate_for_child(sl.handle), sl.kind, sl.maxvalue)
  98.  
  99.     def __setstate__(self, state):
  100.         self._semlock = _multiprocessing.SemLock._rebuild(*state)
  101.         debug('recreated blocker with handle %r' % state[0])
  102.         self._make_methods()
  103.  
  104. #
  105. # Semaphore
  106. #
  107.  
  108. class Semaphore(SemLock):
  109.  
  110.     def __init__(self, value=1):
  111.         SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX)
  112.  
  113.     def get_value(self):
  114.         return self._semlock._get_value()
  115.  
  116.     def __repr__(self):
  117.         try:
  118.             value = self._semlock._get_value()
  119.         except Exception:
  120.             value = 'unknown'
  121.         return '<Semaphore(value=%s)>' % value
  122.  
  123. #
  124. # Bounded semaphore
  125. #
  126.  
  127. class BoundedSemaphore(Semaphore):
  128.  
  129.     def __init__(self, value=1):
  130.         SemLock.__init__(self, SEMAPHORE, value, value)
  131.  
  132.     def __repr__(self):
  133.         try:
  134.             value = self._semlock._get_value()
  135.         except Exception:
  136.             value = 'unknown'
  137.         return '<BoundedSemaphore(value=%s, maxvalue=%s)>' % \
  138.                (value, self._semlock.maxvalue)
  139.  
  140. #
  141. # Non-recursive lock
  142. #
  143.  
  144. class Lock(SemLock):
  145.  
  146.     def __init__(self):
  147.         SemLock.__init__(self, SEMAPHORE, 1, 1)
  148.  
  149.     def __repr__(self):
  150.         try:
  151.             if self._semlock._is_mine():
  152.                 name = current_process().name
  153.                 if threading.current_thread().name != 'MainThread':
  154.                     name += '|' + threading.current_thread().name
  155.             elif self._semlock._get_value() == 1:
  156.                 name = 'None'
  157.             elif self._semlock._count() > 0:
  158.                 name = 'SomeOtherThread'
  159.             else:
  160.                 name = 'SomeOtherProcess'
  161.         except Exception:
  162.             name = 'unknown'
  163.         return '<Lock(owner=%s)>' % name
  164.  
  165. #
  166. # Recursive lock
  167. #
  168.  
  169. class RLock(SemLock):
  170.  
  171.     def __init__(self):
  172.         SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1)
  173.  
  174.     def __repr__(self):
  175.         try:
  176.             if self._semlock._is_mine():
  177.                 name = current_process().name
  178.                 if threading.current_thread().name != 'MainThread':
  179.                     name += '|' + threading.current_thread().name
  180.                 count = self._semlock._count()
  181.             elif self._semlock._get_value() == 1:
  182.                 name, count = 'None', 0
  183.             elif self._semlock._count() > 0:
  184.                 name, count = 'SomeOtherThread', 'nonzero'
  185.             else:
  186.                 name, count = 'SomeOtherProcess', 'nonzero'
  187.         except Exception:
  188.             name, count = 'unknown', 'unknown'
  189.         return '<RLock(%s, %s)>' % (name, count)
  190.  
  191. #
  192. # Condition variable
  193. #
  194.  
  195. class Condition(object):
  196.  
  197.     def __init__(self, lock=None):
  198.         self._lock = lock or RLock()
  199.         self._sleeping_count = Semaphore(0)
  200.         self._woken_count = Semaphore(0)
  201.         self._wait_semaphore = Semaphore(0)
  202.         self._make_methods()
  203.  
  204.     def __getstate__(self):
  205.         assert_spawning(self)
  206.         return (self._lock, self._sleeping_count,
  207.                 self._woken_count, self._wait_semaphore)
  208.  
  209.     def __setstate__(self, state):
  210.         (self._lock, self._sleeping_count,
  211.          self._woken_count, self._wait_semaphore) = state
  212.         self._make_methods()
  213.  
  214.     def __enter__(self):
  215.         return self._lock.__enter__()
  216.  
  217.     def __exit__(self, *args):
  218.         return self._lock.__exit__(*args)
  219.  
  220.     def _make_methods(self):
  221.         self.acquire = self._lock.acquire
  222.         self.release = self._lock.release
  223.  
  224.     def __repr__(self):
  225.         try:
  226.             num_waiters = (self._sleeping_count._semlock._get_value() -
  227.                            self._woken_count._semlock._get_value())
  228.         except Exception:
  229.             num_waiters = 'unknown'
  230.         return '<Condition(%s, %s)>' % (self._lock, num_waiters)
  231.  
  232.     def wait(self, timeout=None):
  233.         assert self._lock._semlock._is_mine(), \
  234.                'must acquire() condition before using wait()'
  235.  
  236.         # indicate that this thread is going to sleep
  237.         self._sleeping_count.release()
  238.  
  239.         # release lock
  240.         count = self._lock._semlock._count()
  241.         for i in xrange(count):
  242.             self._lock.release()
  243.  
  244.         try:
  245.             # wait for notification or timeout
  246.             self._wait_semaphore.acquire(True, timeout)
  247.         finally:
  248.             # indicate that this thread has woken
  249.             self._woken_count.release()
  250.  
  251.             # reacquire lock
  252.             for i in xrange(count):
  253.                 self._lock.acquire()
  254.  
  255.     def notify(self):
  256.         assert self._lock._semlock._is_mine(), 'lock is not owned'
  257.         assert not self._wait_semaphore.acquire(False)
  258.  
  259.         # to take account of timeouts since last notify() we subtract
  260.         # woken_count from sleeping_count and rezero woken_count
  261.         while self._woken_count.acquire(False):
  262.             res = self._sleeping_count.acquire(False)
  263.             assert res
  264.  
  265.         if self._sleeping_count.acquire(False): # try grabbing a sleeper
  266.             self._wait_semaphore.release()      # wake up one sleeper
  267.             self._woken_count.acquire()         # wait for the sleeper to wake
  268.  
  269.             # rezero _wait_semaphore in case a timeout just happened
  270.             self._wait_semaphore.acquire(False)
  271.  
  272.     def notify_all(self):
  273.         assert self._lock._semlock._is_mine(), 'lock is not owned'
  274.         assert not self._wait_semaphore.acquire(False)
  275.  
  276.         # to take account of timeouts since last notify*() we subtract
  277.         # woken_count from sleeping_count and rezero woken_count
  278.         while self._woken_count.acquire(False):
  279.             res = self._sleeping_count.acquire(False)
  280.             assert res
  281.  
  282.         sleepers = 0
  283.         while self._sleeping_count.acquire(False):
  284.             self._wait_semaphore.release()        # wake up one sleeper
  285.             sleepers += 1
  286.  
  287.         if sleepers:
  288.             for i in xrange(sleepers):
  289.                 self._woken_count.acquire()       # wait for a sleeper to wake
  290.  
  291.             # rezero wait_semaphore in case some timeouts just happened
  292.             while self._wait_semaphore.acquire(False):
  293.                 pass
  294.  
  295. #
  296. # Event
  297. #
  298.  
  299. class Event(object):
  300.  
  301.     def __init__(self):
  302.         self._cond = Condition(Lock())
  303.         self._flag = Semaphore(0)
  304.  
  305.     def is_set(self):
  306.         self._cond.acquire()
  307.         try:
  308.             if self._flag.acquire(False):
  309.                 self._flag.release()
  310.                 return True
  311.             return False
  312.         finally:
  313.             self._cond.release()
  314.  
  315.     def set(self):
  316.         self._cond.acquire()
  317.         try:
  318.             self._flag.acquire(False)
  319.             self._flag.release()
  320.             self._cond.notify_all()
  321.         finally:
  322.             self._cond.release()
  323.  
  324.     def clear(self):
  325.         self._cond.acquire()
  326.         try:
  327.             self._flag.acquire(False)
  328.         finally:
  329.             self._cond.release()
  330.  
  331.     def wait(self, timeout=None):
  332.         self._cond.acquire()
  333.         try:
  334.             if self._flag.acquire(False):
  335.                 self._flag.release()
  336.             else:
  337.                 self._cond.wait(timeout)
  338.  
  339.             if self._flag.acquire(False):
  340.                 self._flag.release()
  341.                 return True
  342.             return False
  343.         finally:
  344.             self._cond.release()
  345.