Exemple #1
0
    def acquire(self, blocking=True):
        """acquire ownership of the lock

        if the lock is already owned by the calling greenlet, a counter simply
        gets incremented. if it is owned by a different greenlet then it will
        block until the lock becomes available.

        :param blocking:
            whether to block if the lock is owned by a different greenlet
            (default ``True``)
        :type blocking: bool

        :returns:
            a `bool` indicating whether the lock was acquired. In the default
            case of ``blocking = True`` this will always be the case, but may
            not be otherwise.
        """
        current = compat.getcurrent()
        if self._owner is current:
            self._count += 1
            return True
        if self._locked and not blocking:
            return False
        if self._locked:
            self._waiters.append(compat.getcurrent())
            scheduler.state.mainloop.switch()
        else:
            self._locked = True
            self._owner = current
        self._count = 1
        return True
Exemple #2
0
def local_exception_handler(handler=None, coro=None):
    """add a callback for when an exception occurs in a particular greenlet

    :param handler:
        the callback function, must be a function taking 3 arguments:

        - ``klass`` the exception class
        - ``exc`` the exception instance
        - ``tb`` the traceback object
    :type handler: function
    :param coro:
        the coroutine for which to apply the exception handler (defaults to the
        current coroutine)
    :type coro: greenlet
    """
    if handler is None:
        return lambda h: local_exception_handler(h, coro)

    if not hasattr(handler, "__call__"):
        raise TypeError("exception handlers must be callable")

    if coro is None:
        coro = compat.getcurrent()

    log.info("setting a new coroutine local exception handler")

    state.local_exception_handlers.setdefault(coro, []).append(
            weakref.ref(handler))

    return handler
Exemple #3
0
    def wait(self, timeout=None):
        """wait to be woken up by the condition

        .. note::

            this method will block the current coroutine until a :meth:`notify`
            wakes it back up.

        :raises:
            `RuntimeError` if the underlying lock hasn't been
            :meth:`acquired <Lock.acquire>`
        """
        if not self._is_owned():
            raise RuntimeError("cannot wait on un-acquired lock")

        current = compat.getcurrent()

        waketime = None if timeout is None else time.time() + timeout
        if timeout is not None:
            scheduler.schedule_at(waketime, current)
        self._waiters.append((current, waketime))

        self._lock.release()
        scheduler.state.mainloop.switch()
        self._lock.acquire()

        if timeout is not None:
            timedout = not scheduler._remove_timer(waketime, current)
            if timedout:
                self._waiters.remove((current, waketime))
            return timedout

        return False
Exemple #4
0
def local_outgoing_hook(handler=None, coro=None):
    """add a callback to run every time a greenlet is switched away from

    :param handler:
        the callback function, must be a function taking 2 arguments:

        - an integer indicating whether it is being called as an incoming (1)
          hook or as an outgoing (2) hook (in this case it will always be 2).
        - the coroutine being switched from (in this case it is the one
          indicated by the ``coro`` argument to ``local_outgoing_hook``.

        Be aware that only a weak reference to this function will be held.
    :type handler: function
    :param coro:
        the coroutine for which to apply the trace hook (defaults to current)
    :type coro: greenlet
    """
    if handler is None:
        return lambda h: local_outgoing_hook(h, coro)

    if not hasattr(handler, "__call__"):
        raise TypeError("trace hooks must be callable")

    if coro is None:
        coro = compat.getcurrent()

    log.info("setting a coroutine local outgoing hook callback")

    state.local_from_hooks.setdefault(coro, []).append(
            weakref.ref(handler))

    return handler
Exemple #5
0
    def wait(self, timeout=None):
        """pause the current coroutine until this event is set

        .. note::

            this method will block the current coroutine if :meth:`set` has not
            been called.

        :param timeout:
            the maximum amount of time to block in seconds. the default of
            ``None`` allows indefinite blocking.
        :type timeout: number or None

        :returns:
            ``True`` if a timeout was provided and was hit, otherwise ``False``
        """
        if self._is_set:
            return False

        current = compat.getcurrent() # the waiting greenlet

        waketime = None if timeout is None else time.time() + timeout
        if timeout is not None:
            scheduler.schedule_at(waketime, current)

        self._waiters.append(current)
        scheduler.state.mainloop.switch()

        if timeout is not None:
            if not scheduler._remove_timer(waketime, current):
                self._waiters.remove(current)
                return True

        return False
Exemple #6
0
    def wait(self, timeout=None):
        """wait to be woken up by the condition

        .. note::

            this method will block the current coroutine until a :meth:`notify`
            wakes it back up.

        :raises:
            `RuntimeError` if the underlying lock hasn't been
            :meth:`acquired <Lock.acquire>`
        """
        if not self._is_owned():
            raise RuntimeError("cannot wait on un-acquired lock")

        current = compat.getcurrent()

        waketime = None if timeout is None else time.time() + timeout
        if timeout is not None:
            scheduler.schedule_at(waketime, current)
        self._waiters.append((current, waketime))

        self._lock.release()
        scheduler.state.mainloop.switch()
        self._lock.acquire()

        if timeout is not None:
            timedout = not scheduler._remove_timer(waketime, current)
            if timedout:
                self._waiters.remove((current, waketime))
            return timedout

        return False
Exemple #7
0
def local_outgoing_hook(handler=None, coro=None):
    """add a callback to run every time a greenlet is switched away from

    :param handler:
        the callback function, must be a function taking 2 arguments:

        - an integer indicating whether it is being called as an incoming (1)
          hook or as an outgoing (2) hook (in this case it will always be 2).
        - the coroutine being switched from (in this case it is the one
          indicated by the ``coro`` argument to ``local_outgoing_hook``.

        Be aware that only a weak reference to this function will be held.
    :type handler: function
    :param coro:
        the coroutine for which to apply the trace hook (defaults to current)
    :type coro: greenlet
    """
    if handler is None:
        return lambda h: local_outgoing_hook(h, coro)

    if not hasattr(handler, "__call__"):
        raise TypeError("trace hooks must be callable")

    if coro is None:
        coro = compat.getcurrent()

    log.info("setting a coroutine local outgoing hook callback")

    state.local_from_hooks.setdefault(coro, []).append(weakref.ref(handler))

    return handler
Exemple #8
0
    def acquire(self, blocking=True):
        """decrement the counter, waiting if it is already at 0

        .. note::

            if the counter is already at 0, this method will block the current
            coroutine until a :meth:`release` increments it again.

        :param blocking:
            whether or not to block if the counter is already at 0 (default
            ``True``)
        :type blocking: bool

        :returns:
            a bool, indicating whether the count was decremented (this can only
            be ``False`` if ``blocking`` was ``False`` -- otherwise it would
            have blocked until it could decrement the counter)
        """
        if self._value:
            self._value -= 1
            return True
        if not blocking:
            return False
        self._waiters.append(compat.getcurrent())
        scheduler.state.mainloop.switch()
        return True
Exemple #9
0
def local_exception_handler(handler=None, coro=None):
    """add a callback for when an exception occurs in a particular greenlet

    :param handler:
        the callback function, must be a function taking 3 arguments:

        - ``klass`` the exception class
        - ``exc`` the exception instance
        - ``tb`` the traceback object
    :type handler: function
    :param coro:
        the coroutine for which to apply the exception handler (defaults to the
        current coroutine)
    :type coro: greenlet
    """
    if handler is None:
        return lambda h: local_exception_handler(h, coro)

    if not hasattr(handler, "__call__"):
        raise TypeError("exception handlers must be callable")

    if coro is None:
        coro = compat.getcurrent()

    log.info("setting a new coroutine local exception handler")

    state.local_exception_handlers.setdefault(coro,
                                              []).append(weakref.ref(handler))

    return handler
Exemple #10
0
def pause():
    """pause and reschedule the current greenlet and switch to the next

    .. note:: this method blocks for a short period of time
    """
    schedule(compat.getcurrent())
    state.mainloop.switch()
Exemple #11
0
def pause():
    """pause and reschedule the current greenlet and switch to the next

    .. note:: this method blocks for a short period of time
    """
    schedule(compat.getcurrent())
    state.mainloop.switch()
Exemple #12
0
    def acquire(self, blocking=True):
        """decrement the counter, waiting if it is already at 0

        .. note::

            if the counter is already at 0, this method will block the current
            coroutine until a :meth:`release` increments it again.

        :param blocking:
            whether or not to block if the counter is already at 0 (default
            ``True``)
        :type blocking: bool

        :returns:
            a bool, indicating whether the count was decremented (this can only
            be ``False`` if ``blocking`` was ``False`` -- otherwise it would
            have blocked until it could decrement the counter)
        """
        if self._value:
            self._value -= 1
            return True
        if not blocking:
            return False
        self._waiters.append(compat.getcurrent())
        scheduler.state.mainloop.switch()
        return True
Exemple #13
0
def local_incoming_hook(handler=None, coro=None):
    """add a callback to run every time a greenlet is about to be switched to

    :param handler:
        the callback function, must be a function taking 2 arguments: an
        integer indicating whether it is being called as an incoming (1) hook
        or as an outgoing (2) hook. in this case it will always be 1. be aware
        that only a weak reference to this function will be held.
    :type handler: function
    :param coro:
        the coroutine for which to apply the trace hook (defaults to current)
    :type coro: greenlet
    """
    if handler is None:
        return lambda h: local_incoming_hook(h, coro)

    if not hasattr(handler, "__call__"):
        raise TypeError("trace hooks must be callable")

    if coro is None:
        coro = compat.getcurrent()

    state.local_to_hooks.setdefault(coro, []).append(
            weakref.ref(handler))

    return handler
Exemple #14
0
    def acquire(self, blocking=True):
        """lock the lock, blocking until it becomes available

        .. note::

            this method will block the current coroutine if the lock is not
            already owned.

        :param blocking:
            whether to block if the lock is already owned (default ``True``)
        :type blocking: bool

        :returns:
            a `bool` indicating whether the lock was acquired. In the default
            case of ``blocking = True`` this will always be the case, but may
            not be otherwise.
        """
        current = compat.getcurrent()
        if not blocking:
            locked_already = self._locked
            if not locked_already:
                self._locked = True
                self._owner = current
            return not locked_already
        if self._locked:
            self._waiters.append(current)
            scheduler.state.mainloop.switch()
        else:
            self._locked = True
            self._owner = current
        return True
Exemple #15
0
    def acquire(self, blocking=True):
        """lock the lock, blocking until it becomes available

        .. note::

            this method will block the current coroutine if the lock is not
            already owned.

        :param blocking:
            whether to block if the lock is already owned (default ``True``)
        :type blocking: bool

        :returns:
            a `bool` indicating whether the lock was acquired. In the default
            case of ``blocking = True`` this will always be the case, but may
            not be otherwise.
        """
        current = compat.getcurrent()
        if not blocking:
            locked_already = self._locked
            if not locked_already:
                self._locked = True
                self._owner = current
            return not locked_already
        if self._locked:
            self._waiters.append(current)
            scheduler.state.mainloop.switch()
        else:
            self._locked = True
            self._owner = current
        return True
Exemple #16
0
 def __getattr__(self, name):
     current = compat.getcurrent()
     if current is compat.main_greenlet:
         current = self._main_standin
     local = self._local_data.setdefault(current, {})
     if name not in local:
         raise AttributeError("Local object has no attribute %s" % name)
     return local[name]
Exemple #17
0
def pause_until(unixtime):
    """pause and reschedule the current greenlet until a set time

    :param unixtime: the unix timestamp of when to bring this greenlet back
    :type unixtime: int or float
    """
    schedule_at(unixtime, compat.getcurrent())
    state.mainloop.switch()
Exemple #18
0
 def __getattr__(self, name):
     current = compat.getcurrent()
     if current is compat.main_greenlet:
         current = self._main_standin
     local = self._local_data.setdefault(current, {})
     if name not in local:
         raise AttributeError, "Local object has no attribute %s" % name
     return local[name]
Exemple #19
0
def pause_until(unixtime):
    """pause and reschedule the current greenlet until a set time

    .. note:: this method will block the current greenlet

    :param unixtime: the unix timestamp of when to bring this greenlet back
    :type unixtime: int or float
    """
    schedule_at(unixtime, compat.getcurrent())
    state.mainloop.switch()
Exemple #20
0
def handle_exception(klass, exc, tb, coro=None):
    """run all the registered exception handlers

    the first 3 arguments to this function match the output of
    ``sys.exc_info()``

    :param klass: the exception klass
    :type klass: type
    :param exc: the exception instance
    :type exc: Exception
    :param tb: the traceback object
    :type tb: Traceback
    :param coro:
        behave as though the exception occurred in this coroutine (defaults to
        the current coroutine)
    :type coro: greenlet

    exception handlers run would be all those added with
    :func:`global_exception_handler`, and any added for the relevant coroutine
    with :func:`local_exception_handler`.
    """
    if coro is None:
        coro = compat.getcurrent()

    replacement = []
    for weak in state.local_exception_handlers.get(coro, ()):
        func = weak()
        if func is None:
            continue

        try:
            func(klass, exc, tb)
        except Exception:
            continue

        replacement.append(weak)

    if replacement:
        state.local_exception_handlers[coro][:] = replacement

    replacement = []
    for weak in state.global_exception_handlers:
        func = weak()
        if func is None:
            continue

        try:
            func(klass, exc, tb)
        except Exception:
            continue

        replacement.append(weak)

    state.global_exception_handlers[:] = replacement
Exemple #21
0
def handle_exception(klass, exc, tb, coro=None):
    """run all the registered exception handlers

    the first 3 arguments to this function match the output of
    ``sys.exc_info()``

    :param klass: the exception klass
    :type klass: type
    :param exc: the exception instance
    :type exc: Exception
    :param tb: the traceback object
    :type tb: Traceback
    :param coro:
        behave as though the exception occurred in this coroutine (defaults to
        the current coroutine)
    :type coro: greenlet

    exception handlers run would be all those added with
    :func:`global_exception_handler`, and any added for the relevant coroutine
    with :func:`local_exception_handler`.
    """
    if coro is None:
        coro = compat.getcurrent()

    replacement = []
    for weak in state.local_exception_handlers.get(coro, ()):
        func = weak()
        if func is None:
            continue

        try:
            func(klass, exc, tb)
        except Exception:
            continue

        replacement.append(weak)

    if replacement:
        state.local_exception_handlers[coro][:] = replacement

    replacement = []
    for weak in state.global_exception_handlers:
        func = weak()
        if func is None:
            continue

        try:
            func(klass, exc, tb)
        except Exception:
            continue

        replacement.append(weak)

    state.global_exception_handlers[:] = replacement
Exemple #22
0
    def wait(self, until=0):
        """wait until the count has reached a particular number

        .. note:: this method can block the current greenlet

        :param until:
            the number to wait for the count to get down (or up) to. default 0
        :type until: int
        """
        if self._count != until:
            self._waiters.setdefault(until, []).append(compat.getcurrent())
            scheduler.state.mainloop.switch()
Exemple #23
0
    def wait(self, until=0):
        """wait until the count has reached a particular number

        .. note:: this method can block the current greenlet

        :param until:
            the number to wait for the count to get down (or up) to. default 0
        :type until: int
        """
        if self._count != until:
            self._waiters.setdefault(until, []).append(compat.getcurrent())
            scheduler.state.mainloop.switch()
Exemple #24
0
    def put(self, item, block=True, timeout=None):
        """put an item into the queue

        .. note::

            if the queue was created with a `maxsize` and it is currently
            :meth:`full`, this method will block the calling coroutine until
            another coroutine :meth:`get`\ s an item.

        :param item: the object to put into the queue, can be any type
        :param block:
            whether to block if the queue is already :meth:`full` (default
            ``True``)
        :type block: bool
        :param timeout:
            the maximum time in seconds to block waiting. with the default of
            ``None``, it can wait indefinitely. this is unused if `block` is
            ``False``.
        :type timeout: int, float or None

        :raises:
            :class:`Full` if the queue is :meth:`full` and `block` is
            ``False``, or if `timeout` expires.
        """
        if self.full():
            if not block:
                raise Full()

            current = compat.getcurrent()

            waketime = None if timeout is None else time.time() + timeout
            if timeout is not None:
                scheduler.schedule_at(waketime, current)
            self._waiters.append((current, waketime))

            scheduler.state.mainloop.switch()

            if timeout is not None:
                if not scheduler._remove_timer(waketime, current):
                    self._waiters.remove((current, waketime))
                    raise Full()

        if self._waiters and not self.full():
            scheduler.schedule(self._waiters.popleft()[0])

        if not self._open_tasks:
            self._jobs_done.clear()
        self._open_tasks += 1

        self._put(item)
Exemple #25
0
    def put(self, item, blocking=True, timeout=None):
        """put an item into the queue

        .. note::

            if the queue was created with a `maxsize` and it is currently
            :meth:`full`, this method will block the calling coroutine until
            another coroutine :meth:`get`\ s an item.

        :param item: the object to put into the queue, can be any type
        :param blocking:
            whether to block if the queue is already :meth:`full` (default
            ``True``)
        :type blocking: bool
        :param timeout:
            the maximum time in seconds to block waiting. with the default of
            ``None``, it can wait indefinitely. this is unused if `blocking` is
            ``False``.
        :type timeout: int, float or None

        :raises:
            :class:`Full` if the queue is :meth:`full` and `blocking` is
            ``False``, or if `timeout` expires.
        """
        if self.full():
            if not blocking:
                raise Full()

            current = compat.getcurrent()

            waketime = None if timeout is None else time.time() + timeout
            if timeout is not None:
                scheduler.schedule_at(waketime, current)
            self._waiters.append((current, waketime))

            scheduler.state.mainloop.switch()

            if timeout is not None:
                if not scheduler._remove_timer(waketime, current):
                    self._waiters.remove((current, waketime))
                    raise Full()

        if self._waiters and not self.full():
            scheduler.schedule(self._waiters.popleft()[0])

        if not self._open_tasks:
            self._jobs_done.clear()
        self._open_tasks += 1

        self._put(item)
Exemple #26
0
    def acquire(self, blocking=True):
        """acquire ownership of the lock

        if the lock is already owned by the calling greenlet, a counter simply
        gets incremented. if it is owned by a different greenlet then it will
        block until the lock becomes available.

        .. note::

            this method will block the current coroutine if the lock is not
            already owned by another coroutine.

        :param blocking:
            whether to block if the lock is owned by a different greenlet
            (default ``True``)
        :type blocking: bool

        :returns:
            a `bool` indicating whether the lock was acquired. In the default
            case of ``blocking = True`` this will always be the case, but may
            not be otherwise.
        """
        current = compat.getcurrent()
        if self._owner is current:
            self._count += 1
            return True
        if self._locked and not blocking:
            return False
        if self._locked:
            self._waiters.append(compat.getcurrent())
            scheduler.state.mainloop.switch()
        else:
            self._locked = True
            self._owner = current
        self._count = 1
        return True
Exemple #27
0
    def get(self, block=True, timeout=None):
        """get an item out of the queue

        .. note::

            if `block` is ``True`` (the default) and the queue is
            :meth`empty`, this method will block the current coroutine until
            something has been :meth:`put`.

        :param block:
            whether to block if there is no data yet available (default
            ``True``)
        :type block: bool
        :param timeout:
            the maximum time in seconds to block waiting for data. with the
            default of ``None``, can wait indefinitely. this is unused if
            `block` is ``False``.
        :type timeout: int, float or None

        :raises:
            :class:`Empty` if there is no data in the queue and block is
            ``False``, or `timeout` expires

        :returns: something that was previously :meth:`put` in the queue
        """
        if not self._data:
            if not block:
                raise Empty()

            current = compat.getcurrent()

            waketime = None if timeout is None else time.time() + timeout
            if timeout is not None:
                scheduler.schedule_at(waketime, current)
            self._waiters.append((current, waketime))

            scheduler.state.mainloop.switch()

            if timeout is not None:
                if not scheduler._remove_timer(waketime, current):
                    self._waiters.remove((current, waketime))
                    raise Empty()

        if self.full() and self._waiters:
            scheduler.schedule(self._waiters.popleft()[0])

        return self._get()
Exemple #28
0
    def get(self, blocking=True, timeout=None):
        """get an item out of the queue

        .. note::

            if `blocking` is ``True`` (the default) and the queue is
            :meth`empty`, this method will block the current coroutine until
            something has been :meth:`put`.

        :param blocking:
            whether to block if there is no data yet available (default
            ``True``)
        :type blocking: bool
        :param timeout:
            the maximum time in seconds to block waiting for data. with the
            default of ``None``, can wait indefinitely. this is unused if
            `blocking` is ``False``.
        :type timeout: int, float or None

        :raises:
            :class:`Empty` if there is no data in the queue and blocking is
            ``False``, or `timeout` expires

        :returns: something that was previously :meth:`put` in the queue
        """
        if not self._data:
            if not blocking:
                raise Empty()

            current = compat.getcurrent()

            waketime = None if timeout is None else time.time() + timeout
            if timeout is not None:
                scheduler.schedule_at(waketime, current)
            self._waiters.append((current, waketime))

            scheduler.state.mainloop.switch()

            if timeout is not None:
                if not scheduler._remove_timer(waketime, current):
                    self._waiters.remove((current, waketime))
                    raise Empty()

        if self.full() and self._waiters:
            scheduler.schedule(self._waiters.popleft()[0])

        return self._get()
Exemple #29
0
    def join(self, timeout=None):
        """block until this thread terminates

        :param timeout:
            the maximum time to wait. with the default of ``None``, waits
            indefinitely
        :type timeout: int, float or None

        :raises:
            `RuntimeError` if called inside the thread, or it has not yet been
            started
        """
        if not self._started:
            raise RuntimeError("cannot join thread before it is started")
        if compat.getcurrent() is self._glet:
            raise RuntimeError("cannot join current thread")
        self._finished.wait(timeout)
Exemple #30
0
def remove_local_exception_handler(handler, coro=None):
    """remove a callback from the list of exception handlers for a coroutine

    :param handler: the callback to remove
    :type handler: function
    :param coro: the coroutine for which to remove the local handler
    :type coro: greenlet

    :returns: bool, whether the handler was found (and therefore removed)
    """
    if coro is None:
        coro = compat.getcurrent()

    for i, cb in enumerate(state.local_exception_handlers.get(coro, [])):
        cb = cb()
        if cb is not None and cb is handler:
            state.local_exception_handlers[coro].pop(i)
            return True
    return False
Exemple #31
0
def remove_local_outgoing_hook(handler, coro=None):
    """remove a callback from the outgoing hooks for a particular coro

    :param handler: the callback previously added via local_outgoing_hook
    :type handler: function
    :param coro: the coroutine for which the hook should be removed
    :type coro: greenlet

    :returns: bool, whether the handler was found and removed
    """
    if coro is None:
        coro = compat.getcurrent()

    for i, cb in enumerate(state.local_from_hooks.get(coro, [])):
        cb = cb()
        if cb is not None and cb is handler:
            state.local_from_hooks[coro].pop(i)
            return True
    return False
Exemple #32
0
def remove_local_exception_handler(handler, coro=None):
    """remove a callback from the list of exception handlers for a coroutine

    :param handler: the callback to remove
    :type handler: function
    :param coro: the coroutine for which to remove the local handler
    :type coro: greenlet

    :returns: bool, whether the handler was found (and therefore removed)
    """
    if coro is None:
        coro = compat.getcurrent()

    for i, cb in enumerate(state.local_exception_handlers.get(coro, [])):
        cb = cb()
        if cb is not None and cb is handler:
            state.local_exception_handlers[coro].pop(i)
            log.info("removing a coroutine local exception handler")
            return True
    return False
Exemple #33
0
def remove_local_outgoing_hook(handler, coro=None):
    """remove a callback from the outgoing hooks for a particular coro

    :param handler: the callback previously added via local_outgoing_hook
    :type handler: function
    :param coro: the coroutine for which the hook should be removed
    :type coro: greenlet

    :returns: bool, whether the handler was found and removed
    """
    if coro is None:
        coro = compat.getcurrent()

    for i, cb in enumerate(state.local_from_hooks.get(coro, [])):
        cb = cb()
        if cb is not None and cb is handler:
            log.info("removing a coroutine outgoing local hook callback")
            state.local_from_hooks[coro].pop(i)
            return True
    return False
Exemple #34
0
    def join(self, timeout=None):
        """block until this thread terminates

        .. note::

            this method can block the calling coroutine if the thread has not
            yet completed.

        :param timeout:
            the maximum time to wait. with the default of ``None``, waits
            indefinitely
        :type timeout: int, float or None

        :raises:
            `RuntimeError` if called inside the thread, or it has not yet been
            started
        """
        if not self._started:
            raise RuntimeError("cannot join thread before it is started")
        if compat.getcurrent() is self._glet:
            raise RuntimeError("cannot join current thread")
        self._finished.wait(timeout)
Exemple #35
0
    def release(self):
        """release one ownership of the lock

        if the calling greenlet has :meth:`acquired <acquire>` the lock more
        than once this will simply decrement the counter. if this is a final
        release then a waiting greenlet is awoken

        :raises:
            `RuntimeError` if the calling greenlet is not the lock's owner
        """
        if not self._locked or self._owner is not compat.getcurrent():
            raise RuntimeError("cannot release un-acquired lock")
        self._count -= 1
        if self._count == 0:
            self._owner = None
            if self._waiters:
                waiter = self._waiters.popleft()
                self._locked = True
                self._owner = waiter
                scheduler.state.awoken_from_events.add(waiter)
            else:
                self._locked = False
                self._owner = None
Exemple #36
0
    def release(self):
        """release one ownership of the lock

        if the calling greenlet has :meth:`acquired <acquire>` the lock more
        than once this will simply decrement the counter. if this is a final
        release then a waiting greenlet is awoken

        :raises:
            `RuntimeError` if the calling greenlet is not the lock's owner
        """
        if not self._locked or self._owner is not compat.getcurrent():
            raise RuntimeError("cannot release un-acquired lock")
        self._count -= 1
        if self._count == 0:
            self._owner = None
            if self._waiters:
                waiter = self._waiters.popleft()
                self._locked = True
                self._owner = waiter
                scheduler.state.awoken_from_events.add(waiter)
            else:
                self._locked = False
                self._owner = None
Exemple #37
0
    def wait(self, timeout=None):
        """pause the current coroutine until this event is set

        .. note::

            this method will block the current coroutine if :meth:`set` has not
            been called.

        :param timeout:
            the maximum amount of time to block in seconds. the default of
            ``None`` allows indefinite blocking.
        :type timeout: number or None

        :returns:
            ``True`` if a timeout was provided and was hit, otherwise ``False``
        """
        if self._is_set:
            return False

        current = compat.getcurrent()  # the waiting greenlet

        waketime = None if timeout is None else time.time() + timeout
        if timeout is not None:
            scheduler.schedule_at(waketime, current)

        self._waiters.append(current)
        scheduler.state.mainloop.switch()

        if timeout is not None:
            if not scheduler._remove_timer(waketime, current):
                scheduler.state.awoken_from_events.discard(current)
                if current in self._waiters:
                    self._waiters.remove(current)
                return True

        return False
Exemple #38
0
def _current_thread():
    if compat.getcurrent() is compat.main_greenlet:
        return _main_thread
    return Thread._active.get(compat.getcurrent(), _dummy_thread)
Exemple #39
0
 def __setattr__(self, name, value):
     current = compat.getcurrent()
     if current is compat.main_greenlet:
         current = self._main_standin
     self._local_data.setdefault(current, {})[name] = value
Exemple #40
0
 def _is_owned(self):
     return self._owner is compat.getcurrent()
Exemple #41
0
 def _is_owned(self):
     return self._owner is compat.getcurrent()
Exemple #42
0
 def __setattr__(self, name, value):
     current = compat.getcurrent()
     if current is compat.main_greenlet:
         current = self._main_standin
     self._local_data.setdefault(current, {})[name] = value
Exemple #43
0
def pause():
    "pause and reschedule the current greenlet and switch to the next"
    schedule(compat.getcurrent())
    state.mainloop.switch()