# Path: guv/semaphore.py
# class Semaphore:
#     """An unbounded semaphore
# 
#     Optionally initialize with a resource *count*, then :meth:`acquire` and :meth:`release`
#     resources as needed. Attempting to :meth:`acquire` when count* is zero suspends the calling
#     greenthread until *count* becomes nonzero again.
# 
#     This is API-compatible with :class:`threading.Semaphore`.
# 
#     It is a context manager, and thus can be used in a with block::
# 
#       sem = Semaphore(2)
#       with sem:
#         do_some_stuff()
# 
#     If not specified, *value* defaults to 1.
# 
#     It is possible to limit acquire time::
# 
#       sem = Semaphore()
#       ok = sem.acquire(timeout=0.1)
#       # True if acquired, False if timed out.
#     """
# 
#     def __init__(self, value=1):
#         self.counter = value
#         if value < 0:
#             raise ValueError("Semaphore must be initialized with a positive "
#                              "number, got %s" % value)
#         self._waiters = set()
# 
#     def __repr__(self):
#         params = (self.__class__.__name__, hex(id(self)),
#                   self.counter, len(self._waiters))
#         return '<%s at %s c=%s _w[%s]>' % params
# 
#     def __str__(self):
#         params = (self.__class__.__name__, self.counter, len(self._waiters))
#         return '<%s c=%s _w[%s]>' % params
# 
#     def locked(self):
#         """Returns true if a call to acquire would block.
#         """
#         return self.counter <= 0
# 
#     def bounded(self):
#         """Returns False; for consistency with
#         :class:`~guv.semaphore.CappedSemaphore`.
#         """
#         return False
# 
#     def acquire(self, blocking=True, timeout=None):
#         """Acquire a semaphore
# 
#         This function behaves like :meth:`threading.Lock.acquire`.
# 
#         When invoked without arguments: if the internal counter is larger than
#         zero on entry, decrement it by one and return immediately. If it is zero
#         on entry, block, waiting until some other thread has called release() to
#         make it larger than zero. This is done with proper interlocking so that
#         if multiple acquire() calls are blocked, release() will wake exactly one
#         of them up. The implementation may pick one at random, so the order in
#         which blocked threads are awakened should not be relied on. There is no
#         return value in this case.
# 
#         When invoked with blocking set to true, do the same thing as when called
#         without arguments, and return true.
# 
#         When invoked with blocking set to false, do not block. If a call without
#         an argument would block, return false immediately; otherwise, do the
#         same thing as when called without arguments, and return true.
#         """
#         if not blocking and timeout is not None:
#             raise ValueError('must not specify timeout for non-blocking acquire')
# 
#         if not blocking and self.locked():
#             return False
# 
#         if isinstance(timeout, (float, int)) and timeout < 0:
#             timeout = None
# 
#         if self.counter <= 0:
#             self._waiters.add(greenlet.getcurrent())
#             try:
#                 if timeout is not None:
#                     ok = False
#                     with Timeout(timeout, False):
#                         while self.counter <= 0:
#                             hubs.get_hub().switch()
#                         ok = True
#                     if not ok:
#                         return False
#                 else:
#                     while self.counter <= 0:
#                         # running = hubs.get_hub().running
#                         # if not running:
#                         #     log.warn('Loop is no longer running, potential deadlock: (at {}) {}\n'
#                         #              'waiters: {}'
#                         #              .format(id(self), self, self._waiters))
#                         #     return
#                         hubs.get_hub().switch()
#             finally:
#                 self._waiters.discard(greenlet.getcurrent())
#         self.counter -= 1
#         return True
# 
#     def __enter__(self):
#         self.acquire()
# 
#     def release(self, blocking=True):
#         """Release a semaphore, incrementing the internal counter by one. When
#         it was zero on entry and another thread is waiting for it to become
#         larger than zero again, wake up that thread.
# 
#         The *blocking* argument is for consistency with CappedSemaphore and is
#         ignored
#         """
#         self.counter += 1
#         if self._waiters:
#             hubs.get_hub().schedule_call_now(self._do_acquire)
#         return True
# 
#     def _do_acquire(self):
#         if self._waiters and self.counter > 0:
#             waiter = self._waiters.pop()
#             waiter.switch()
# 
#     def __exit__(self, typ, val, tb):
#         self.release()
# 
#     @property
#     def balance(self):
#         """An integer value that represents how many new calls to
#         :meth:`acquire` or :meth:`release` would be needed to get the counter to
#         0.  If it is positive, then its value is the number of acquires that can
#         happen before the next acquire would block.  If it is negative, it is
#         the negative of the number of releases that would be required in order
#         to make the counter 0 again (one more release would push the counter to
#         1 and unblock acquirers).  It takes into account how many greenthreads
#         are currently blocking in :meth:`acquire`.
#         """
#         # positive means there are free items
#         # zero means there are no free items but nobody has requested one
#         # negative means there are requests for items, but no items
#         return self.counter - len(self._waiters)


from ..semaphore import Semaphore
import greenlet

__all__ = ['RLock']


class RLock(object):
    green = True

    def __init__(self):
        self._block = Semaphore(1)
        self._owner = None
        self._count = 0

    def __repr__(self):
        return "<%s at %s _block=%s _count=%r _owner=%r)>" % (
            self.__class__.__name__,
            hex(id(self)),
            self._block,
            self._count,
            self._owner)

    def acquire(self, blocking=1):
        me = greenlet.getcurrent()
        if self._owner is me:

# Path: guv/semaphore.py
# class Semaphore:
#     """An unbounded semaphore
# 
#     Optionally initialize with a resource *count*, then :meth:`acquire` and :meth:`release`
#     resources as needed. Attempting to :meth:`acquire` when count* is zero suspends the calling
#     greenthread until *count* becomes nonzero again.
# 
#     This is API-compatible with :class:`threading.Semaphore`.
# 
#     It is a context manager, and thus can be used in a with block::
# 
#       sem = Semaphore(2)
#       with sem:
#         do_some_stuff()
# 
#     If not specified, *value* defaults to 1.
# 
#     It is possible to limit acquire time::
# 
#       sem = Semaphore()
#       ok = sem.acquire(timeout=0.1)
#       # True if acquired, False if timed out.
#     """
# 
#     def __init__(self, value=1):
#         self.counter = value
#         if value < 0:
#             raise ValueError("Semaphore must be initialized with a positive "
#                              "number, got %s" % value)
#         self._waiters = set()
# 
#     def __repr__(self):
#         params = (self.__class__.__name__, hex(id(self)),
#                   self.counter, len(self._waiters))
#         return '<%s at %s c=%s _w[%s]>' % params
# 
#     def __str__(self):
#         params = (self.__class__.__name__, self.counter, len(self._waiters))
#         return '<%s c=%s _w[%s]>' % params
# 
#     def locked(self):
#         """Returns true if a call to acquire would block.
#         """
#         return self.counter <= 0
# 
#     def bounded(self):
#         """Returns False; for consistency with
#         :class:`~guv.semaphore.CappedSemaphore`.
#         """
#         return False
# 
#     def acquire(self, blocking=True, timeout=None):
#         """Acquire a semaphore
# 
#         This function behaves like :meth:`threading.Lock.acquire`.
# 
#         When invoked without arguments: if the internal counter is larger than
#         zero on entry, decrement it by one and return immediately. If it is zero
#         on entry, block, waiting until some other thread has called release() to
#         make it larger than zero. This is done with proper interlocking so that
#         if multiple acquire() calls are blocked, release() will wake exactly one
#         of them up. The implementation may pick one at random, so the order in
#         which blocked threads are awakened should not be relied on. There is no
#         return value in this case.
# 
#         When invoked with blocking set to true, do the same thing as when called
#         without arguments, and return true.
# 
#         When invoked with blocking set to false, do not block. If a call without
#         an argument would block, return false immediately; otherwise, do the
#         same thing as when called without arguments, and return true.
#         """
#         if not blocking and timeout is not None:
#             raise ValueError('must not specify timeout for non-blocking acquire')
# 
#         if not blocking and self.locked():
#             return False
# 
#         if isinstance(timeout, (float, int)) and timeout < 0:
#             timeout = None
# 
#         if self.counter <= 0:
#             self._waiters.add(greenlet.getcurrent())
#             try:
#                 if timeout is not None:
#                     ok = False
#                     with Timeout(timeout, False):
#                         while self.counter <= 0:
#                             hubs.get_hub().switch()
#                         ok = True
#                     if not ok:
#                         return False
#                 else:
#                     while self.counter <= 0:
#                         # running = hubs.get_hub().running
#                         # if not running:
#                         #     log.warn('Loop is no longer running, potential deadlock: (at {}) {}\n'
#                         #              'waiters: {}'
#                         #              .format(id(self), self, self._waiters))
#                         #     return
#                         hubs.get_hub().switch()
#             finally:
#                 self._waiters.discard(greenlet.getcurrent())
#         self.counter -= 1
#         return True
# 
#     def __enter__(self):
#         self.acquire()
# 
#     def release(self, blocking=True):
#         """Release a semaphore, incrementing the internal counter by one. When
#         it was zero on entry and another thread is waiting for it to become
#         larger than zero again, wake up that thread.
# 
#         The *blocking* argument is for consistency with CappedSemaphore and is
#         ignored
#         """
#         self.counter += 1
#         if self._waiters:
#             hubs.get_hub().schedule_call_now(self._do_acquire)
#         return True
# 
#     def _do_acquire(self):
#         if self._waiters and self.counter > 0:
#             waiter = self._waiters.pop()
#             waiter.switch()
# 
#     def __exit__(self, typ, val, tb):
#         self.release()
# 
#     @property
#     def balance(self):
#         """An integer value that represents how many new calls to
#         :meth:`acquire` or :meth:`release` would be needed to get the counter to
#         0.  If it is positive, then its value is the number of acquires that can
#         happen before the next acquire would block.  If it is negative, it is
#         the negative of the number of releases that would be required in order
#         to make the counter 0 again (one more release would push the counter to
#         1 and unblock acquirers).  It takes into account how many greenthreads
#         are currently blocking in :meth:`acquire`.
#         """
#         # positive means there are free items
#         # zero means there are no free items but nobody has requested one
#         # negative means there are requests for items, but no items
#         return self.counter - len(self._waiters)


# Path: guv/green/lock.py
from ..semaphore import Semaphore
import greenlet


__all__ = ['RLock']


class RLock(object):
    green = True

    def __init__(self):
        self._block = Semaphore(1)
        self._owner = None
        self._count = 0

    def __repr__(self):
        return "<%s at %s _block=%s _count=%r _owner=%r)>" % (
            self.__class__.__name__,
            hex(id(self)),
            self._block,
            self._count,
            self._owner)

    def acquire(self, blocking=1):
        me = greenlet.getcurrent()
        if self._owner is me:

            self._count = self._count + 1