Skip to content

Commit 532de8c

Browse files
committed
Base StrictLocks on Gevent 1.5 RLock
1 parent 7946dec commit 532de8c

File tree

1 file changed

+92
-2
lines changed

1 file changed

+92
-2
lines changed

labthings/core/lock.py

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,97 @@
1-
from threading import RLock
1+
from gevent.hub import getcurrent
2+
from gevent._semaphore import Semaphore
23

34
from .exceptions import LockError
45

56

7+
class RLock(object):
8+
"""
9+
A mutex that can be acquired more than once by the same greenlet.
10+
A mutex can only be locked by one greenlet at a time. A single greenlet
11+
can `acquire` the mutex as many times as desired, though. Each call to
12+
`acquire` must be paired with a matching call to `release`.
13+
It is an error for a greenlet that has not acquired the mutex
14+
to release it.
15+
Instances are context managers.
16+
"""
17+
18+
__slots__ = (
19+
'_block',
20+
'_owner',
21+
'_count',
22+
'__weakref__',
23+
)
24+
25+
def __init__(self):
26+
self._block = Semaphore(1)
27+
self._owner = None
28+
self._count = 0
29+
30+
def __repr__(self):
31+
return "<%s at 0x%x _block=%s _count=%r _owner=%r)>" % (
32+
self.__class__.__name__,
33+
id(self),
34+
self._block,
35+
self._count,
36+
self._owner)
37+
38+
def acquire(self, blocking=True, timeout=None):
39+
"""
40+
Acquire the mutex, blocking if *blocking* is true, for up to
41+
*timeout* seconds.
42+
.. versionchanged:: 1.5a4
43+
Added the *timeout* parameter.
44+
:return: A boolean indicating whether the mutex was acquired.
45+
"""
46+
me = getcurrent()
47+
if self._owner is me:
48+
self._count = self._count + 1
49+
return 1
50+
rc = self._block.acquire(blocking, timeout)
51+
if rc:
52+
self._owner = me
53+
self._count = 1
54+
return rc
55+
56+
def __enter__(self):
57+
return self.acquire()
58+
59+
def release(self):
60+
"""
61+
Release the mutex.
62+
Only the greenlet that originally acquired the mutex can
63+
release it.
64+
"""
65+
if self._owner is not getcurrent():
66+
raise RuntimeError("cannot release un-acquired lock")
67+
self._count = count = self._count - 1
68+
if not count:
69+
self._owner = None
70+
self._block.release()
71+
72+
def __exit__(self, typ, value, tb):
73+
self.release()
74+
75+
# Internal methods used by condition variables
76+
77+
def _acquire_restore(self, count_owner):
78+
count, owner = count_owner
79+
self._block.acquire()
80+
self._count = count
81+
self._owner = owner
82+
83+
def _release_save(self):
84+
count = self._count
85+
self._count = 0
86+
owner = self._owner
87+
self._owner = None
88+
self._block.release()
89+
return (count, owner)
90+
91+
def _is_owned(self):
92+
return self._owner is getcurrent()
93+
94+
695
class StrictLock:
796
"""
897
Class that behaves like a Python RLock,
@@ -16,9 +105,10 @@ class StrictLock:
16105
timeout (int): Time in seconds acquisition will wait before raising an exception
17106
"""
18107

19-
def __init__(self, timeout=1):
108+
def __init__(self, timeout=1, name=None):
20109
self._lock = RLock()
21110
self.timeout = timeout
111+
self.name = name
22112

23113
def locked(self):
24114
return self._lock.locked()

0 commit comments

Comments
 (0)