Revision 7e8841bd lib/locking.py
b/lib/locking.py | ||
---|---|---|
52 | 52 |
return wrap |
53 | 53 |
|
54 | 54 |
|
55 |
class RunningTimeout(object): |
|
56 |
"""Class to calculate remaining timeout when doing several operations. |
|
57 |
|
|
58 |
""" |
|
59 |
__slots__ = [ |
|
60 |
"_allow_negative", |
|
61 |
"_start_time", |
|
62 |
"_time_fn", |
|
63 |
"_timeout", |
|
64 |
] |
|
65 |
|
|
66 |
def __init__(self, timeout, allow_negative, _time_fn=time.time): |
|
67 |
"""Initializes this class. |
|
68 |
|
|
69 |
@type timeout: float |
|
70 |
@param timeout: Timeout duration |
|
71 |
@type allow_negative: bool |
|
72 |
@param allow_negative: Whether to return values below zero |
|
73 |
@param _time_fn: Time function for unittests |
|
74 |
|
|
75 |
""" |
|
76 |
object.__init__(self) |
|
77 |
|
|
78 |
if timeout is not None and timeout < 0.0: |
|
79 |
raise ValueError("Timeout must not be negative") |
|
80 |
|
|
81 |
self._timeout = timeout |
|
82 |
self._allow_negative = allow_negative |
|
83 |
self._time_fn = _time_fn |
|
84 |
|
|
85 |
self._start_time = None |
|
86 |
|
|
87 |
def Remaining(self): |
|
88 |
"""Returns the remaining timeout. |
|
89 |
|
|
90 |
""" |
|
91 |
if self._timeout is None: |
|
92 |
return None |
|
93 |
|
|
94 |
# Get start time on first calculation |
|
95 |
if self._start_time is None: |
|
96 |
self._start_time = self._time_fn() |
|
97 |
|
|
98 |
# Calculate remaining time |
|
99 |
remaining_timeout = self._start_time + self._timeout - self._time_fn() |
|
100 |
|
|
101 |
if not self._allow_negative: |
|
102 |
# Ensure timeout is always >= 0 |
|
103 |
return max(0.0, remaining_timeout) |
|
104 |
|
|
105 |
return remaining_timeout |
|
106 |
|
|
107 |
|
|
55 | 108 |
class _SingleNotifyPipeConditionWaiter(object): |
56 | 109 |
"""Helper class for SingleNotifyPipeCondition |
57 | 110 |
|
... | ... | |
777 | 830 |
|
778 | 831 |
# We need to keep track of how long we spent waiting for a lock. The |
779 | 832 |
# timeout passed to this function is over all lock acquires. |
780 |
remaining_timeout = timeout |
|
781 |
if timeout is None: |
|
782 |
start = None |
|
783 |
calc_remaining_timeout = lambda: None |
|
784 |
else: |
|
785 |
start = time.time() |
|
786 |
calc_remaining_timeout = lambda: max(0.0, (start + timeout) - time.time()) |
|
833 |
running_timeout = RunningTimeout(timeout, False) |
|
787 | 834 |
|
788 | 835 |
try: |
789 | 836 |
if names is not None: |
... | ... | |
794 | 841 |
names = sorted(names) |
795 | 842 |
|
796 | 843 |
return self.__acquire_inner(names, False, shared, |
797 |
calc_remaining_timeout, test_notify)
|
|
844 |
running_timeout.Remaining, test_notify)
|
|
798 | 845 |
|
799 | 846 |
else: |
800 | 847 |
# If no names are given acquire the whole set by not letting new names |
... | ... | |
807 | 854 |
# anyway, though, so we'll get the list lock exclusively as well in |
808 | 855 |
# order to be able to do add() on the set while owning it. |
809 | 856 |
if not self.__lock.acquire(shared=shared, |
810 |
timeout=calc_remaining_timeout()):
|
|
857 |
timeout=running_timeout.Remaining()):
|
|
811 | 858 |
raise _AcquireTimeout() |
812 | 859 |
try: |
813 | 860 |
# note we own the set-lock |
814 | 861 |
self._add_owned() |
815 | 862 |
|
816 | 863 |
return self.__acquire_inner(self.__names(), True, shared, |
817 |
calc_remaining_timeout, test_notify)
|
|
864 |
running_timeout.Remaining, test_notify)
|
|
818 | 865 |
except: |
819 | 866 |
# We shouldn't have problems adding the lock to the owners list, but |
820 | 867 |
# if we did we'll try to release this lock and re-raise exception. |
... | ... | |
827 | 874 |
return None |
828 | 875 |
|
829 | 876 |
def __acquire_inner(self, names, want_all, shared, timeout_fn, test_notify): |
830 |
""" |
|
877 |
"""Inner logic for acquiring a number of locks. |
|
878 |
|
|
879 |
@param names: Names of the locks to be acquired |
|
880 |
@param want_all: Whether all locks in the set should be acquired |
|
881 |
@param shared: Whether to acquire in shared mode |
|
882 |
@param timeout_fn: Function returning remaining timeout |
|
883 |
@param test_notify: Special callback function for unittesting |
|
831 | 884 |
|
832 | 885 |
""" |
833 | 886 |
acquire_list = [] |
... | ... | |
863 | 916 |
test_notify_fn = None |
864 | 917 |
|
865 | 918 |
timeout = timeout_fn() |
866 |
if timeout is not None and timeout < 0: |
|
867 |
raise _AcquireTimeout() |
|
868 | 919 |
|
869 | 920 |
try: |
870 | 921 |
# raises LockError if the lock was deleted |
Also available in: Unified diff