def synchronized(name, external=False):
    """Synchronization decorator.

    Decorating a method like so:
    @synchronized('mylock')
    def foo(self, *args):
       ...

    ensures that only one thread will execute the bar method at a time.

    Different methods can share the same lock:
    @synchronized('mylock')
    def foo(self, *args):
       ...

    @synchronized('mylock')
    def bar(self, *args):
       ...

    This way only one of either foo or bar can be executing at a time.

    The external keyword argument denotes whether this lock should work across
    multiple processes. This means that if two different workers both run a
    a method decorated with @synchronized('mylock', external=True), only one
    of them will execute at a time.

    """

    def wrap(f):
        @functools.wraps(f)
        def inner(*args, **kwargs):
            # NOTE(soren): If we ever go natively threaded, this will be racy.
            #              See http://stackoverflow.com/questions/5390569/dyn\
            #              amically-allocating-and-destroying-mutexes
            if name not in _semaphores:
                _semaphores[name] = semaphore.Semaphore()
            sem = _semaphores[name]
            LOG.debug(_('Attempting to grab semaphore "%(lock)s" for method '
                        '"%(method)s"...' % {'lock': name,
                                             'method': f.__name__}))
            with sem:
                if external:
                    LOG.debug(_('Attempting to grab file lock "%(lock)s" for '
                                'method "%(method)s"...' %
                                {'lock': name, 'method': f.__name__}))
                    lock_file_path = os.path.join(FLAGS.lock_path,
                                                  'nova-%s.lock' % name)
                    lock = lockfile.FileLock(lock_file_path)
                else:
                    lock = _NoopContextManager()

                with lock:
                    retval = f(*args, **kwargs)

            # If no-one else is waiting for it, delete it.
            # See note about possible raciness above.
            if not 1 < sem.balance:
                del _semaphores[name]

            return retval
        return inner
    return wrap
dataset/ETHPy150Open nii-cloud/dodai-compute/nova/utils.py/synchronized/swapped operands of `<`