Skip to content
utils.py 1.49 KiB
Newer Older
#!/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