#!/usr/bin/env python #coding=utf8 ''' Some helpers used by cc-server. ''' from threading import Lock class Acquires(object): ''' Context manager used to acquire more than one lock at once. It works rely on the fact that if locks are always acquired in the same order, we can't enter in a deadlock situation. Usage is very simple: >>> a = Lock() >>> b = Lock() >>> with Acquires(b, a): ... print 'locked' ... .. seealso:: http://dabeaz.blogspot.com/2009/11/python-thread-deadlock-avoidance_20.html ''' def __init__(self, *locks): self._locks = sorted(set(locks), key=lambda x: id(x)) def __enter__(self): for lock in self._locks: lock.acquire() def __exit__(self, exc_type, exc_value, traceback): for lock in self._locks: lock.release() class AcquiresAllOrNone(Acquires): ''' Class that extend Acquires to allow to release all lock if one of them is not free. ''' # Global acquire lock: acquirelock = Lock() def __enter__(self): while True: with self.acquirelock: acquired = [] for lock in self._locks: if not lock.acquire(False): for lock_acquired in acquired: lock_acquired.release() break else: acquired.append(lock) else: break