import threading


def critical_section(cs_lock: threading.Lock):
    """
    Decorator which uses acquires the specified lock when entering in the decorated function
    and releases it once out of the decorated function.
    :param cs_lock:
    :return:
    """
    def _critical_section(f):
        def _critical_section_wrapper(*args, **kwargs):
            cs_lock.acquire()
            ret = f(*args, **kwargs)
            cs_lock.release()
            return ret
        return _critical_section_wrapper
    return _critical_section