Specifying `blocking` and `timeout` when acquiring lock as a context manager

Neil D. Cerutti neilc at norwich.edu
Fri Aug 8 14:35:28 EDT 2014


On 8/8/2014 12:16 PM, Chris Angelico wrote:
> On Sat, Aug 9, 2014 at 2:05 AM, Neil D. Cerutti <neilc at norwich.edu> wrote:
>> Perhaps defer release, a la a common Go pattern:
>>
>> with contextlib.ExitStack() as stack:
>>      acquired = lock.acquire(blocking=False)
>>      if acquired:
>>          stack.callback(lock.release)
>>          do_stuff
>
> There's a race condition in that - an unexpected exception could
> happen between those two. Are you able to set the callback to be a
> "release if acquired" atomic operation?

Doesn't any natural looking use of blocking=False suffer from the same 
race condition? What's the correct way to use it?

Here's another attempt at context managing:

@contextlib.contextmanager
def release_if_acquired(lock, blocking=True, timeout=-1):
     acquired = lock.acquire(blocking, timeout)
     if acquired:
         yield acquired
         lock.release()
     else:
         yield acquired

with release_if_acquired(lock, blocking=False) as acquired:
     if acquired:
         do_stuff

-- 
Neil Cerutti




More information about the Python-list mailing list