Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r58335:475f3eb6c7d7
Date: 2012-10-21 06:10 +0200
http://bitbucket.org/pypy/pypy/changeset/475f3eb6c7d7/
Log: Add timeout to RLock.acquire()
diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -31,6 +31,26 @@
## sys.stderr.write(msg)
+def parse_acquire_args(space, blocking, timeout):
+ if not blocking and timeout != -1.0:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "can't specify a timeout for a non-blocking call"))
+ if timeout < 0.0 and timeout != -1.0:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "timeout value must be strictly positive"))
+ if not blocking:
+ microseconds = 0
+ elif timeout == -1.0:
+ microseconds = -1
+ else:
+ timeout *= 1e6
+ if timeout > float(TIMEOUT_MAX):
+ raise OperationError(space.w_ValueError, space.wrap(
+ "timeout value is too large"))
+ microseconds = r_longlong(timeout)
+ return microseconds
+
+
class Lock(Wrappable):
"A wrappable box around an interp-level lock object."
@@ -49,22 +69,7 @@
With an argument, this will only block if the argument is true,
and the return value reflects whether the lock is acquired.
The blocking operation is interruptible."""
- if not blocking and timeout != -1.0:
- raise OperationError(space.w_ValueError, space.wrap(
- "can't specify a timeout for a non-blocking call"))
- if timeout < 0.0 and timeout != -1.0:
- raise OperationError(space.w_ValueError, space.wrap(
- "timeout value must be strictly positive"))
- if not blocking:
- microseconds = 0
- elif timeout == -1.0:
- microseconds = -1
- else:
- timeout *= 1e6
- if timeout > float(TIMEOUT_MAX):
- raise OperationError(space.w_ValueError, space.wrap(
- "timeout value is too large"))
- microseconds = r_longlong(timeout)
+ microseconds = parse_acquire_args(space, blocking, timeout)
mylock = self.lock
result = mylock.acquire_timed(microseconds)
return space.newbool(result)
@@ -150,8 +155,8 @@
return space.wrap("<%s owner=%d count=%d>" % (
typename, self.rlock_owner, self.rlock_count))
- @unwrap_spec(blocking=bool)
- def acquire_w(self, space, blocking=True):
+ @unwrap_spec(blocking=bool, timeout=float)
+ def acquire_w(self, space, blocking=True, timeout=-1.0):
"""Lock the lock. `blocking` indicates whether we should wait
for the lock to be available or not. If `blocking` is False
and another thread holds the lock, the method will return False
@@ -164,6 +169,7 @@
Precisely, if the current thread already holds the lock, its
internal counter is simply incremented. If nobody holds the lock,
the lock is taken and its internal counter initialized to 1."""
+ microseconds = parse_acquire_args(space, blocking, timeout)
tid = thread.get_ident()
if self.rlock_count > 0 and tid == self.rlock_owner:
try:
@@ -177,7 +183,7 @@
if self.rlock_count > 0 or not self.lock.acquire(False):
if not blocking:
return space.w_False
- r = self.lock.acquire(True)
+ r = self.lock.acquire_timed(microseconds)
if r:
assert self.rlock_count == 0
self.rlock_owner = tid
@@ -212,9 +218,12 @@
else:
return space.w_False
- @unwrap_spec(count=int, owner=int)
- def acquire_restore_w(self, space, count, owner):
+ def acquire_restore_w(self, space, w_saved_state):
"""For internal use by `threading.Condition`."""
+ # saved_state is the value returned by release_save()
+ w_count, w_owner = space.unpackiterable(w_saved_state, 2)
+ count = space.int_w(w_count)
+ owner = space.int_w(w_owner)
r = True
if not self.lock.acquire(False):
r = self.lock.acquire(True)
diff --git a/pypy/module/thread/test/test_lock.py
b/pypy/module/thread/test/test_lock.py
--- a/pypy/module/thread/test/test_lock.py
+++ b/pypy/module/thread/test/test_lock.py
@@ -128,3 +128,9 @@
with lock:
assert lock._is_owned() is True
+ def test_timeout(self):
+ import _thread
+ lock = _thread.RLock()
+ assert lock.acquire() is True
+ assert lock.acquire(False) is True
+ assert lock.acquire(True, timeout=.1) is True
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit