183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Module implementing synchronization primitives
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# multiprocessing/synchronize.py
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Copyright (c) 2006-2008, R Oudkerk
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# All rights reserved.
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Redistribution and use in source and binary forms, with or without
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# modification, are permitted provided that the following conditions
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# are met:
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 1. Redistributions of source code must retain the above copyright
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#    notice, this list of conditions and the following disclaimer.
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 2. Redistributions in binary form must reproduce the above copyright
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#    notice, this list of conditions and the following disclaimer in the
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#    documentation and/or other materials provided with the distribution.
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 3. Neither the name of author nor the names of any contributors may be
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#    used to endorse or promote products derived from this software
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#    without specific prior written permission.
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# SUCH DAMAGE.
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = [
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', 'Event'
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ]
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport threading
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport os
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom time import time as _time, sleep as _sleep
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport _multiprocessing
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom multiprocessing.process import current_process
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom multiprocessing.util import Finalize, register_after_fork, debug
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom multiprocessing.forking import assert_spawning, Popen
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Try to import the mp.synchronize module cleanly, if it fails
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# raise ImportError for platforms lacking a working sem_open implementation.
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# See issue 3770
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtry:
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    from _multiprocessing import SemLock
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexcept (ImportError):
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    raise ImportError("This platform lacks a functioning sem_open" +
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                      " implementation, therefore, the required" +
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                      " synchronization primitives needed will not" +
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                      " function, see issue 3770.")
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Constants
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehRECURSIVE_MUTEX, SEMAPHORE = range(2)
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehSEM_VALUE_MAX = _multiprocessing.SemLock.SEM_VALUE_MAX
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Base class for semaphores and mutexes; wraps `_multiprocessing.SemLock`
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass SemLock(object):
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, kind, value, maxvalue):
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        debug('created semlock with handle %s' % sl.handle)
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._make_methods()
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if sys.platform != 'win32':
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            def _after_fork(obj):
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                obj._semlock._after_fork()
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            register_after_fork(self, _after_fork)
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _make_methods(self):
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.acquire = self._semlock.acquire
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.release = self._semlock.release
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __enter__(self):
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._semlock.__enter__()
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __exit__(self, *args):
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._semlock.__exit__(*args)
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __getstate__(self):
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert_spawning(self)
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sl = self._semlock
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return (Popen.duplicate_for_child(sl.handle), sl.kind, sl.maxvalue)
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __setstate__(self, state):
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._semlock = _multiprocessing.SemLock._rebuild(*state)
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        debug('recreated blocker with handle %r' % state[0])
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._make_methods()
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Semaphore
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Semaphore(SemLock):
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, value=1):
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX)
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_value(self):
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._semlock._get_value()
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            value = self._semlock._get_value()
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except Exception:
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            value = 'unknown'
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return '<Semaphore(value=%s)>' % value
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Bounded semaphore
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass BoundedSemaphore(Semaphore):
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, value=1):
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        SemLock.__init__(self, SEMAPHORE, value, value)
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            value = self._semlock._get_value()
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except Exception:
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            value = 'unknown'
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return '<BoundedSemaphore(value=%s, maxvalue=%s)>' % \
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh               (value, self._semlock.maxvalue)
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Non-recursive lock
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Lock(SemLock):
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self):
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        SemLock.__init__(self, SEMAPHORE, 1, 1)
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self._semlock._is_mine():
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name = current_process().name
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if threading.current_thread().name != 'MainThread':
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    name += '|' + threading.current_thread().name
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif self._semlock._get_value() == 1:
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name = 'None'
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif self._semlock._count() > 0:
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name = 'SomeOtherThread'
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name = 'SomeOtherProcess'
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except Exception:
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            name = 'unknown'
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return '<Lock(owner=%s)>' % name
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Recursive lock
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass RLock(SemLock):
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self):
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1)
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self._semlock._is_mine():
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name = current_process().name
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if threading.current_thread().name != 'MainThread':
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    name += '|' + threading.current_thread().name
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                count = self._semlock._count()
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif self._semlock._get_value() == 1:
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name, count = 'None', 0
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif self._semlock._count() > 0:
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name, count = 'SomeOtherThread', 'nonzero'
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                name, count = 'SomeOtherProcess', 'nonzero'
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except Exception:
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            name, count = 'unknown', 'unknown'
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return '<RLock(%s, %s)>' % (name, count)
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Condition variable
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Condition(object):
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, lock=None):
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._lock = lock or RLock()
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._sleeping_count = Semaphore(0)
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._woken_count = Semaphore(0)
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._wait_semaphore = Semaphore(0)
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._make_methods()
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __getstate__(self):
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert_spawning(self)
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return (self._lock, self._sleeping_count,
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._woken_count, self._wait_semaphore)
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __setstate__(self, state):
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        (self._lock, self._sleeping_count,
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh         self._woken_count, self._wait_semaphore) = state
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._make_methods()
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __enter__(self):
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._lock.__enter__()
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __exit__(self, *args):
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self._lock.__exit__(*args)
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _make_methods(self):
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.acquire = self._lock.acquire
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.release = self._lock.release
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self):
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            num_waiters = (self._sleeping_count._semlock._get_value() -
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                           self._woken_count._semlock._get_value())
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except Exception:
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            num_waiters = 'unkown'
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return '<Condition(%s, %s)>' % (self._lock, num_waiters)
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def wait(self, timeout=None):
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert self._lock._semlock._is_mine(), \
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh               'must acquire() condition before using wait()'
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # indicate that this thread is going to sleep
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._sleeping_count.release()
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # release lock
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        count = self._lock._semlock._count()
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for i in xrange(count):
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._lock.release()
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # wait for notification or timeout
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._wait_semaphore.acquire(True, timeout)
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # indicate that this thread has woken
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._woken_count.release()
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # reacquire lock
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for i in xrange(count):
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._lock.acquire()
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def notify(self):
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert self._lock._semlock._is_mine(), 'lock is not owned'
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert not self._wait_semaphore.acquire(False)
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # to take account of timeouts since last notify() we subtract
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # woken_count from sleeping_count and rezero woken_count
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while self._woken_count.acquire(False):
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            res = self._sleeping_count.acquire(False)
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert res
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self._sleeping_count.acquire(False): # try grabbing a sleeper
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._wait_semaphore.release()      # wake up one sleeper
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._woken_count.acquire()         # wait for the sleeper to wake
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # rezero _wait_semaphore in case a timeout just happened
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._wait_semaphore.acquire(False)
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def notify_all(self):
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert self._lock._semlock._is_mine(), 'lock is not owned'
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        assert not self._wait_semaphore.acquire(False)
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # to take account of timeouts since last notify*() we subtract
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # woken_count from sleeping_count and rezero woken_count
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while self._woken_count.acquire(False):
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            res = self._sleeping_count.acquire(False)
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            assert res
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sleepers = 0
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while self._sleeping_count.acquire(False):
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._wait_semaphore.release()        # wake up one sleeper
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            sleepers += 1
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if sleepers:
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for i in xrange(sleepers):
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._woken_count.acquire()       # wait for a sleeper to wake
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # rezero wait_semaphore in case some timeouts just happened
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            while self._wait_semaphore.acquire(False):
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pass
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Event
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Event(object):
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self):
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._cond = Condition(Lock())
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._flag = Semaphore(0)
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def is_set(self):
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._cond.acquire()
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self._flag.acquire(False):
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._flag.release()
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return True
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._cond.release()
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def set(self):
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._cond.acquire()
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._flag.acquire(False)
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._flag.release()
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._cond.notify_all()
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._cond.release()
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def clear(self):
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._cond.acquire()
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._flag.acquire(False)
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._cond.release()
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def wait(self, timeout=None):
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._cond.acquire()
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self._flag.acquire(False):
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._flag.release()
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._cond.wait(timeout)
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self._flag.acquire(False):
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self._flag.release()
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return True
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return False
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self._cond.release()
345