示例#1
0
 def _wait_core(self, timeout, catch=Timeout):
     # The core of the wait implementation, handling
     # switching and linking. If *catch* is set to (),
     # a timeout that elapses will be allowed to be raised.
     # Returns a true value if the wait succeeded without timing out.
     switch = getcurrent().switch  # pylint:disable=undefined-variable
     self.rawlink(switch)
     try:
         with Timeout._start_new_or_dummy(timeout) as timer:
             try:
                 if self.hub is None:
                     self.hub = get_hub()
                 result = self.hub.switch()
                 if result is not self:  # pragma: no cover
                     raise InvalidSwitchError(
                         'Invalid switch into Event.wait(): %r' %
                         (result, ))
                 return True
             except catch as ex:
                 if ex is not timer:
                     raise
                 # test_set_and_clear and test_timeout in test_threading
                 # rely on the exact return values, not just truthish-ness
                 return False
     finally:
         self.unlink(switch)
示例#2
0
文件: queue.py 项目: gevent/gevent
    def __init__(self, maxsize=None, items=(), _warn_depth=2):
        if maxsize is not None and maxsize <= 0:
            if maxsize == 0:
                import warnings
                warnings.warn(
                    'Queue(0) now equivalent to Queue(None); if you want a channel, use Channel',
                    DeprecationWarning,
                    stacklevel=_warn_depth)
            maxsize = None

        self._maxsize = maxsize if maxsize is not None else -1
        # Explicitly maintain order for getters and putters that block
        # so that callers can consistently rely on getting things out
        # in the apparent order they went in. This was once required by
        # imap_unordered. Previously these were set() objects, and the
        # items put in the set have default hash() and eq() methods;
        # under CPython, since new objects tend to have increasing
        # hash values, this tended to roughly maintain order anyway,
        # but that's not true under PyPy. An alternative to a deque
        # (to avoid the linear scan of remove()) might be an
        # OrderedDict, but it's 2.7 only; we don't expect to have so
        # many waiters that removing an arbitrary element is a
        # bottleneck, though.
        self.getters = collections.deque()
        self.putters = collections.deque()
        self.hub = get_hub()
        self._event_unlock = None
        self.queue = self._create_queue(items)
示例#3
0
    def _check_and_notify(self):
        # If this object is ready to be notified, begin the process.
        if self.ready() and self._links and not self._notifier:
            if self.hub is None:
                self.hub = get_hub()

            self._notifier = self.hub.loop.run_callback(self._notify_links)
示例#4
0
def iwait_on_objects(objects, timeout=None, count=None):
    """
    Iteratively yield *objects* as they are ready, until all (or *count*) are ready
    or *timeout* expired.

    :param objects: A sequence (supporting :func:`len`) containing objects
        implementing the wait protocol (rawlink() and unlink()).
    :keyword int count: If not `None`, then a number specifying the maximum number
        of objects to wait for. If ``None`` (the default), all objects
        are waited for.
    :keyword float timeout: If given, specifies a maximum number of seconds
        to wait. If the timeout expires before the desired waited-for objects
        are available, then this method returns immediately.

    .. seealso:: :func:`wait`

    .. versionchanged:: 1.1a1
       Add the *count* parameter.
    .. versionchanged:: 1.1a2
       No longer raise :exc:`LoopExit` if our caller switches greenlets
       in between items yielded by this function.
    """
    # QQQ would be nice to support iterable here that can be generated slowly (why?)
    hub = get_hub()
    if objects is None:
        return [hub.join(timeout=timeout)]
    return _WaitIterator(objects, hub, timeout, count)
示例#5
0
    def __init__(self, maxsize=None, items=(), _warn_depth=2):
        if maxsize is not None and maxsize <= 0:
            if maxsize == 0:
                import warnings
                warnings.warn(
                    'Queue(0) now equivalent to Queue(None); if you want a channel, use Channel',
                    DeprecationWarning,
                    stacklevel=_warn_depth)
            maxsize = None

        self._maxsize = maxsize if maxsize is not None else -1
        # Explicitly maintain order for getters and putters that block
        # so that callers can consistently rely on getting things out
        # in the apparent order they went in. This was once required by
        # imap_unordered. Previously these were set() objects, and the
        # items put in the set have default hash() and eq() methods;
        # under CPython, since new objects tend to have increasing
        # hash values, this tended to roughly maintain order anyway,
        # but that's not true under PyPy. An alternative to a deque
        # (to avoid the linear scan of remove()) might be an
        # OrderedDict, but it's 2.7 only; we don't expect to have so
        # many waiters that removing an arbitrary element is a
        # bottleneck, though.
        self.getters = collections.deque()
        self.putters = collections.deque()
        self.hub = get_hub()
        self._event_unlock = None
        self.queue = self._create_queue(items)
示例#6
0
    def __init__(self,
                 seconds=None,
                 exception=None,
                 ref=True,
                 priority=-1,
                 _one_shot=False):
        BaseException.__init__(self)
        self.seconds = seconds
        self.exception = exception
        self._one_shot = _one_shot
        if seconds is None:
            # Avoid going through the timer codepath if no timeout is
            # desired; this avoids some CFFI interactions on PyPy that can lead to a
            # RuntimeError if this implementation is used during an `import` statement. See
            # https://bitbucket.org/pypy/pypy/issues/2089/crash-in-pypy-260-linux64-with-gevent-11b1
            # and https://github.com/gevent/gevent/issues/618.
            # Plus, in general, it should be more efficient

            self.timer = _FakeTimer
        else:
            # XXX: A timer <= 0 could cause libuv to block the loop; we catch
            # that case in libuv/loop.py
            self.timer = get_hub().loop.timer(seconds or 0.0,
                                              ref=ref,
                                              priority=priority)
示例#7
0
文件: queue.py 项目: gevent/gevent
 def __init__(self, maxsize=1):
     # We take maxsize to simplify certain kinds of code
     if maxsize != 1:
         raise ValueError("Channels have a maxsize of 1")
     self.getters = collections.deque()
     self.putters = collections.deque()
     self.hub = get_hub()
     self._event_unlock = None
示例#8
0
 def __init__(self, maxsize=1):
     # We take maxsize to simplify certain kinds of code
     if maxsize != 1:
         raise ValueError("Channels have a maxsize of 1")
     self.getters = collections.deque()
     self.putters = collections.deque()
     self.hub = get_hub()
     self._event_unlock = None
示例#9
0
def getnameinfo(sockaddr, flags):
    """
    getnameinfo(sockaddr, flags) -> (host, port)

    Get host and port for a sockaddr.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.getnameinfo(sockaddr, flags)
示例#10
0
def gethostbyname(hostname):
    """
    gethostbyname(host) -> address

    Return the IP address (a string of the form '255.255.255.255') for a host.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyname(hostname)
示例#11
0
def gethostbyname(hostname):
    """
    gethostbyname(host) -> address

    Return the IP address (a string of the form '255.255.255.255') for a host.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyname(hostname)
示例#12
0
def getnameinfo(sockaddr, flags):
    """
    getnameinfo(sockaddr, flags) -> (host, port)

    Get host and port for a sockaddr.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.getnameinfo(sockaddr, flags)
示例#13
0
def gethostbyaddr(ip_address):
    """
    gethostbyaddr(ip_address) -> (name, aliaslist, addresslist)

    Return the true host name, a list of aliases, and a list of IP addresses,
    for a host.  The host argument is a string giving a host name or IP number.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyaddr(ip_address)
示例#14
0
def gethostbyaddr(ip_address):
    """
    gethostbyaddr(ip_address) -> (name, aliaslist, addresslist)

    Return the true host name, a list of aliases, and a list of IP addresses,
    for a host.  The host argument is a string giving a host name or IP number.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyaddr(ip_address)
示例#15
0
def gethostbyname_ex(hostname):
    """
    gethostbyname_ex(host) -> (name, aliaslist, addresslist)

    Return the true host name, a list of aliases, and a list of IP addresses,
    for a host.  The host argument is a string giving a host name or IP number.
    Resolve host and port into list of address info entries.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyname_ex(hostname)
示例#16
0
def gethostbyname_ex(hostname):
    """
    gethostbyname_ex(host) -> (name, aliaslist, addresslist)

    Return the true host name, a list of aliases, and a list of IP addresses,
    for a host.  The host argument is a string giving a host name or IP number.
    Resolve host and port into list of address info entries.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.gethostbyname_ex(hostname)
示例#17
0
 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
     # pylint:disable=function-redefined, undefined-variable
     # Also, on Python 3, we need to translate into the special enums.
     # Our lower-level resolvers, including the thread and blocking, which use _socket,
     # function simply with integers.
     addrlist = get_hub().resolver.getaddrinfo(host, port, family, type,
                                               proto, flags)
     result = [(_intenum_converter(af, AddressFamily),
                _intenum_converter(socktype,
                                   SocketKind), proto, canonname, sa)
               for af, socktype, proto, canonname, sa in addrlist]
     return result
示例#18
0
 def _capture_hub(self, create):
     # Subclasses should call this as the first action from any
     # public method that could, in theory, block and switch
     # to the hub. This may release the GIL.
     if self.hub is None:
         # This next line might release the GIL.
         current_hub = get_hub() if create else get_hub_if_exists()
         if current_hub is None:
             return
         # We have the GIL again. Did anything change? If so,
         # we lost the race.
         if self.hub is None:
             self.hub = current_hub
示例#19
0
 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
     # pylint:disable=function-redefined, undefined-variable
     # Also, on Python 3, we need to translate into the special enums.
     # Our lower-level resolvers, including the thread and blocking, which use _socket,
     # function simply with integers.
     addrlist = get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags)
     result = [
         (_intenum_converter(af, AddressFamily),
          _intenum_converter(socktype, SocketKind),
          proto, canonname, sa)
         for af, socktype, proto, canonname, sa
         in addrlist
     ]
     return result
示例#20
0
    def __init__(self):
        # Also previously, AsyncResult maintained the order of notifications, but Event
        # did not; this implementation does not. (Event also only call callbacks one
        # time (set), but AsyncResult permitted duplicates.)

        # HOWEVER, gevent.queue.Queue does guarantee the order of getters relative
        # to putters. Some existing documentation out on the net likes to refer to
        # gevent as "deterministic", such that running the same program twice will
        # produce results in the same order (so long as I/O isn't involved). This could
        # be an argument to maintain order. (One easy way to do that while guaranteeing
        # uniqueness would be with a 2.7+ OrderedDict.)
        self._links = set()
        self.hub = get_hub()
        self._notifier = None
示例#21
0
def wait_read(fileno, timeout=None, timeout_exc=_NONE):
    """
    wait_read(fileno, timeout=None, [timeout_exc=None]) -> None

    Block the current greenlet until *fileno* is ready to read.

    For the meaning of the other parameters and possible exceptions,
    see :func:`wait`.

    .. seealso:: :func:`cancel_wait`
    """
    hub = get_hub()
    io = hub.loop.io(fileno, 1)
    try:
        return wait_on_watcher(io, timeout, timeout_exc, hub)
    finally:
        io.close()
def wait_read(fileno, timeout=None, timeout_exc=_NONE):
    """
    wait_read(fileno, timeout=None, [timeout_exc=None]) -> None

    Block the current greenlet until *fileno* is ready to read.

    For the meaning of the other parameters and possible exceptions,
    see :func:`wait`.

    .. seealso:: :func:`cancel_wait`
    """
    hub = get_hub()
    io = hub.loop.io(fileno, 1)
    try:
        return wait_on_watcher(io, timeout, timeout_exc, hub)
    finally:
        io.close()
示例#23
0
def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0):
    """
    Resolve host and port into list of address info entries.

    Translate the host/port argument into a sequence of 5-tuples that contain
    all the necessary arguments for creating a socket connected to that service.
    host is a domain name, a string representation of an IPv4/v6 address or
    None. port is a string service name such as 'http', a numeric port number or
    None. By passing None as the value of host and port, you can pass NULL to
    the underlying C API.

    The family, type and proto arguments can be optionally specified in order to
    narrow the list of addresses returned. Passing zero as a value for each of
    these arguments selects the full range of results.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags)
示例#24
0
def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0):
    """
    Resolve host and port into list of address info entries.

    Translate the host/port argument into a sequence of 5-tuples that contain
    all the necessary arguments for creating a socket connected to that service.
    host is a domain name, a string representation of an IPv4/v6 address or
    None. port is a string service name such as 'http', a numeric port number or
    None. By passing None as the value of host and port, you can pass NULL to
    the underlying C API.

    The family, type and proto arguments can be optionally specified in order to
    narrow the list of addresses returned. Passing zero as a value for each of
    these arguments selects the full range of results.

    .. seealso:: :doc:`/dns`
    """
    return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags)
def _primitive_wait(watcher, timeout, timeout_exc, hub):
    if watcher.callback is not None:
        raise ConcurrentObjectUseError(
            'This socket is already used by another greenlet: %r' %
            (watcher.callback, ))

    if hub is None:
        hub = get_hub()

    if timeout is None:
        hub.wait(watcher)
        return

    timeout = Timeout._start_new_or_dummy(
        timeout, (timeout_exc if timeout_exc is not _NONE or timeout is None
                  else _timeout_error('timed out')))

    with timeout:
        hub.wait(watcher)
示例#26
0
def _primitive_wait(watcher, timeout, timeout_exc, hub):
    if watcher.callback is not None:
        raise ConcurrentObjectUseError('This socket is already used by another greenlet: %r'
                                       % (watcher.callback, ))

    if hub is None:
        hub = get_hub()

    if timeout is None:
        hub.wait(watcher)
        return

    timeout = Timeout._start_new_or_dummy(
        timeout,
        (timeout_exc
         if timeout_exc is not _NONE or timeout is None
         else _timeout_error('timed out')))

    with timeout:
        hub.wait(watcher)
def wait_write(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
    """
    wait_write(fileno, timeout=None, [timeout_exc=None]) -> None

    Block the current greenlet until *fileno* is ready to write.

    For the meaning of the other parameters and possible exceptions,
    see :func:`wait`.

    .. deprecated:: 1.1
       The keyword argument *event* is ignored. Applications should not pass this parameter.
       In the future, doing so will become an error.

    .. seealso:: :func:`cancel_wait`
    """
    # pylint:disable=unused-argument
    hub = get_hub()
    io = hub.loop.io(fileno, 2)
    try:
        return wait_on_watcher(io, timeout, timeout_exc, hub)
    finally:
        io.close()
示例#28
0
def wait_write(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
    """
    wait_write(fileno, timeout=None, [timeout_exc=None]) -> None

    Block the current greenlet until *fileno* is ready to write.

    For the meaning of the other parameters and possible exceptions,
    see :func:`wait`.

    .. deprecated:: 1.1
       The keyword argument *event* is ignored. Applications should not pass this parameter.
       In the future, doing so will become an error.

    .. seealso:: :func:`cancel_wait`
    """
    # pylint:disable=unused-argument
    hub = get_hub()
    io = hub.loop.io(fileno, 2)
    try:
        return wait_on_watcher(io, timeout, timeout_exc, hub)
    finally:
        io.close()
def wait_on_objects(objects=None, timeout=None, count=None):
    """
    Wait for ``objects`` to become ready or for event loop to finish.

    If ``objects`` is provided, it must be a list containing objects
    implementing the wait protocol (rawlink() and unlink() methods):

    - :class:`gevent.Greenlet` instance
    - :class:`gevent.event.Event` instance
    - :class:`gevent.lock.Semaphore` instance
    - :class:`gevent.subprocess.Popen` instance

    If ``objects`` is ``None`` (the default), ``wait()`` blocks until
    the current event loop has nothing to do (or until ``timeout`` passes):

    - all greenlets have finished
    - all servers were stopped
    - all event loop watchers were stopped.

    If ``count`` is ``None`` (the default), wait for all ``objects``
    to become ready.

    If ``count`` is a number, wait for (up to) ``count`` objects to become
    ready. (For example, if count is ``1`` then the function exits
    when any object in the list is ready).

    If ``timeout`` is provided, it specifies the maximum number of
    seconds ``wait()`` will block.

    Returns the list of ready objects, in the order in which they were
    ready.

    .. seealso:: :func:`iwait`
    """
    if objects is None:
        hub = get_hub()
        return hub.join(timeout=timeout)  # pylint:disable=
    return list(iwait_on_objects(objects, timeout, count))
示例#30
0
def wait_on_objects(objects=None, timeout=None, count=None):
    """
    Wait for ``objects`` to become ready or for event loop to finish.

    If ``objects`` is provided, it must be a list containing objects
    implementing the wait protocol (rawlink() and unlink() methods):

    - :class:`gevent.Greenlet` instance
    - :class:`gevent.event.Event` instance
    - :class:`gevent.lock.Semaphore` instance
    - :class:`gevent.subprocess.Popen` instance

    If ``objects`` is ``None`` (the default), ``wait()`` blocks until
    the current event loop has nothing to do (or until ``timeout`` passes):

    - all greenlets have finished
    - all servers were stopped
    - all event loop watchers were stopped.

    If ``count`` is ``None`` (the default), wait for all ``objects``
    to become ready.

    If ``count`` is a number, wait for (up to) ``count`` objects to become
    ready. (For example, if count is ``1`` then the function exits
    when any object in the list is ready).

    If ``timeout`` is provided, it specifies the maximum number of
    seconds ``wait()`` will block.

    Returns the list of ready objects, in the order in which they were
    ready.

    .. seealso:: :func:`iwait`
    """
    if objects is None:
        hub = get_hub()
        return hub.join(timeout=timeout) # pylint:disable=
    return list(iwait_on_objects(objects, timeout, count))
示例#31
0
def iwait_on_objects(objects, timeout=None, count=None):
    """
    Iteratively yield *objects* as they are ready, until all (or *count*) are ready
    or *timeout* expired.

    If you will only be consuming a portion of the *objects*, you should
    do so inside a ``with`` block on this object to avoid leaking resources::

        with gevent.iwait((a, b, c)) as it:
            for i in it:
                if i is a:
                    break

    :param objects: A sequence (supporting :func:`len`) containing objects
        implementing the wait protocol (rawlink() and unlink()).
    :keyword int count: If not `None`, then a number specifying the maximum number
        of objects to wait for. If ``None`` (the default), all objects
        are waited for.
    :keyword float timeout: If given, specifies a maximum number of seconds
        to wait. If the timeout expires before the desired waited-for objects
        are available, then this method returns immediately.

    .. seealso:: :func:`wait`

    .. versionchanged:: 1.1a1
       Add the *count* parameter.
    .. versionchanged:: 1.1a2
       No longer raise :exc:`LoopExit` if our caller switches greenlets
       in between items yielded by this function.
    .. versionchanged:: 1.4
       Add support to use the returned object as a context manager.
    """
    # QQQ would be nice to support iterable here that can be generated slowly (why?)
    hub = get_hub()
    if objects is None:
        return [hub.join(timeout=timeout)]
    return _WaitIterator(objects, hub, timeout, count)
    def _capture_hub(self, create):
        # Subclasses should call this as the first action from any
        # public method that could, in theory, block and switch
        # to the hub. This may release the GIL. It may
        # raise InvalidThreadUseError if the result would

        # First, detect a dead hub and drop it.
        while 1:
            my_hub = self.hub
            if my_hub is None:
                break
            if my_hub.dead:  # dead is a property, could release GIL
                # back, holding GIL
                if self.hub is my_hub:
                    self.hub = None
                    my_hub = None
                    break
            else:
                break

        if self.hub is None:
            # This next line might release the GIL.
            current_hub = get_hub() if create else get_hub_if_exists()

            # We have the GIL again. Did anything change? If so,
            # we lost the race.
            if self.hub is None:
                self.hub = current_hub

        if self.hub is not None and self.hub.thread_ident != _get_thread_ident(
        ):
            raise InvalidThreadUseError(
                self.hub,
                get_hub_if_exists(),
                getcurrent()  # pylint:disable=undefined-variable
            )
        return self.hub
示例#33
0
    def __init__(self, run=None, *args, **kwargs):
        """
        :param args: The arguments passed to the ``run`` function.
        :param kwargs: The keyword arguments passed to the ``run`` function.
        :keyword callable run: The callable object to run. If not given, this object's
            `_run` method will be invoked (typically defined by subclasses).

        .. versionchanged:: 1.1b1
            The ``run`` argument to the constructor is now verified to be a callable
            object. Previously, passing a non-callable object would fail after the greenlet
            was spawned.

        .. versionchanged:: 1.3b1
           The ``GEVENT_TRACK_GREENLET_TREE`` configuration value may be set to
           a false value to disable ``spawn_tree_locals``, ``spawning_greenlet``,
           and ``spawning_stack``. The first two will be None in that case, and the
           latter will be empty.

        .. versionchanged:: 1.5
           Greenlet objects are now more careful to verify that their ``parent`` is really
           a gevent hub, raising a ``TypeError`` earlier instead of an ``AttributeError`` later.
        """
        # The attributes are documented in the .rst file

        # greenlet.greenlet(run=None, parent=None)
        # Calling it with both positional arguments instead of a keyword
        # argument (parent=get_hub()) speeds up creation of this object ~30%:
        # python -m timeit -s 'import gevent' 'gevent.Greenlet()'
        # Python 3.5: 2.70usec with keywords vs 1.94usec with positional
        # Python 3.4: 2.32usec with keywords vs 1.74usec with positional
        # Python 3.3: 2.55usec with keywords vs 1.92usec with positional
        # Python 2.7: 1.73usec with keywords vs 1.40usec with positional

        # Timings taken Feb 21 2018 prior to integration of #755
        # python -m perf timeit -s 'import gevent' 'gevent.Greenlet()'
        # 3.6.4       : Mean +- std dev: 1.08 us +- 0.05 us
        # 2.7.14      : Mean +- std dev: 1.44 us +- 0.06 us
        # PyPy2 5.10.0: Mean +- std dev: 2.14 ns +- 0.08 ns

        # After the integration of spawning_stack, spawning_greenlet,
        # and spawn_tree_locals on that same date:
        # 3.6.4       : Mean +- std dev: 8.92 us +- 0.36 us ->  8.2x
        # 2.7.14      : Mean +- std dev: 14.8 us +- 0.5 us  -> 10.2x
        # PyPy2 5.10.0: Mean +- std dev: 3.24 us +- 0.17 us ->  1.5x

        # Compiling with Cython gets us to these numbers:
        # 3.6.4        : Mean +- std dev: 3.63 us +- 0.14 us
        # 2.7.14       : Mean +- std dev: 3.37 us +- 0.20 us
        # PyPy2 5.10.0 : Mean +- std dev: 4.44 us +- 0.28 us

        # Switching to reified frames and some more tuning gets us here:
        # 3.7.2        : Mean +- std dev: 2.53 us +- 0.15 us
        # 2.7.16       : Mean +- std dev: 2.35 us +- 0.12 us
        # PyPy2 7.1    : Mean +- std dev: 11.6 us +- 0.4 us

        # Compared to the released 1.4 (tested at the same time):
        # 3.7.2        : Mean +- std dev: 3.21 us +- 0.32 us
        # 2.7.16       : Mean +- std dev: 3.11 us +- 0.19 us
        # PyPy2 7.1    : Mean +- std dev: 12.3 us +- 0.8 us

        _greenlet__init__(self, None, get_hub())

        if run is not None:
            self._run = run

        # If they didn't pass a callable at all, then they must
        # already have one. Note that subclassing to override the run() method
        # itself has never been documented or supported.
        if not callable(self._run):
            raise TypeError("The run argument or self._run must be callable")

        self.args = args
        self.kwargs = kwargs
        self.value = None

        #: An event, such as a timer or a callback that fires. It is established in
        #: start() and start_later() as those two objects, respectively.
        #: Once this becomes non-None, the Greenlet cannot be started again. Conversely,
        #: kill() and throw() check for non-None to determine if this object has ever been
        #: scheduled for starting. A placeholder _cancelled_start_event is assigned by them to prevent
        #: the greenlet from being started in the future, if necessary.
        #: In the usual case, this transitions as follows: None -> event -> _start_completed_event.
        #: A value of None means we've never been started.
        self._start_event = None

        self._notifier = None
        self._formatted_info = None
        self._links = []
        self._ident = None

        # Initial state: None.
        # Completed successfully: (None, None, None)
        # Failed with exception: (t, v, dump_traceback(tb)))
        self._exc_info = None

        if GEVENT_CONFIG.track_greenlet_tree:
            spawner = getcurrent()  # pylint:disable=undefined-variable
            self.spawning_greenlet = wref(spawner)
            try:
                self.spawn_tree_locals = spawner.spawn_tree_locals
            except AttributeError:
                self.spawn_tree_locals = {}
                if get_generic_parent(spawner) is not None:  # pylint:disable=undefined-variable
                    # The main greenlet has no parent.
                    # Its children get separate locals.
                    spawner.spawn_tree_locals = self.spawn_tree_locals

            self.spawning_stack = _extract_stack(self.spawning_stack_limit)
            # Don't copy the spawning greenlet's
            # '_spawning_stack_frames' into ours. That's somewhat
            # confusing, and, if we're not careful, a deep spawn tree
            # can lead to excessive memory usage (an infinite spawning
            # tree could lead to unbounded memory usage without care
            # --- see https://github.com/gevent/gevent/issues/1371)
            # The _spawning_stack_frames may be cleared out later if we access spawning_stack
        else:
            # None is the default for all of these in Cython, but we
            # need to declare them for pure-Python mode.
            self.spawning_greenlet = None
            self.spawn_tree_locals = None
            self.spawning_stack = None
示例#34
0
 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):  # pylint:disable=function-redefined
     return get_hub().resolver.getaddrinfo(host, port, family, type, proto,
                                           flags)
示例#35
0
    def __init__(self, run=None, *args, **kwargs):
        """
        :param args: The arguments passed to the ``run`` function.
        :param kwargs: The keyword arguments passed to the ``run`` function.
        :keyword callable run: The callable object to run. If not given, this object's
            `_run` method will be invoked (typically defined by subclasses).

        .. versionchanged:: 1.1b1
            The ``run`` argument to the constructor is now verified to be a callable
            object. Previously, passing a non-callable object would fail after the greenlet
            was spawned.

        .. rubric:: Attributes

        .. attribute:: value

            Holds the value returned by the function if the greenlet has
            finished successfully. Until then, or if it finished in error, `None`.

            .. tip:: Recall that a greenlet killed with the default
                     :class:`GreenletExit` is considered to have finished
                     successfully, and the `GreenletExit` exception will be
                     its value.


        .. attribute:: spawn_tree_locals

            A dictionary that is shared between all the greenlets
            in a "spawn tree", that is, a spawning greenlet and all
            its descendent greenlets. All children of the main (root)
            greenlet start their own spawn trees. Assign a new dictionary
            to this attribute on an instance of this class to create a new
            spawn tree (as far as locals are concerned).

            .. versionadded:: 1.3a2

        .. attribute:: spawning_greenlet

            A weak-reference to the greenlet that was current when this object
            was created. Note that the :attr:`parent` attribute is always the
            hub.

            .. versionadded:: 1.3a2

        .. attribute:: spawning_stack

           A lightweight frame-like object capturing the stack when
           this greenlet was created as well as the stack when the spawning
           greenlet was created (if applicable). This can be passed to
           :func:`traceback.print_stack`.

            .. versionadded:: 1.3a2

        .. attribute:: spawning_stack_limit

            A class attribute specifying how many levels of the spawning
            stack will be kept. Specify a smaller number for higher performance,
            spawning greenlets, specify a larger value for improved debugging.

            .. versionadded:: 1.3a2

        .. versionchanged:: 1.3b1
           The ``GEVENT_TRACK_GREENLET_TREE`` configuration value may be set to
           a false value to disable ``spawn_tree_locals``, ``spawning_greenlet``,
           and ``spawning_stack``. The first two will be None in that case, and the
           latter will be empty.
        """
        # greenlet.greenlet(run=None, parent=None)
        # Calling it with both positional arguments instead of a keyword
        # argument (parent=get_hub()) speeds up creation of this object ~30%:
        # python -m timeit -s 'import gevent' 'gevent.Greenlet()'
        # Python 3.5: 2.70usec with keywords vs 1.94usec with positional
        # Python 3.4: 2.32usec with keywords vs 1.74usec with positional
        # Python 3.3: 2.55usec with keywords vs 1.92usec with positional
        # Python 2.7: 1.73usec with keywords vs 1.40usec with positional

        # Timings taken Feb 21 2018 prior to integration of #755
        # python -m perf timeit -s 'import gevent' 'gevent.Greenlet()'
        # 3.6.4       : Mean +- std dev: 1.08 us +- 0.05 us
        # 2.7.14      : Mean +- std dev: 1.44 us +- 0.06 us
        # PyPy2 5.10.0: Mean +- std dev: 2.14 ns +- 0.08 ns

        # After the integration of spawning_stack, spawning_greenlet,
        # and spawn_tree_locals on that same date:
        # 3.6.4       : Mean +- std dev: 8.92 us +- 0.36 us ->  8.2x
        # 2.7.14      : Mean +- std dev: 14.8 us +- 0.5 us  -> 10.2x
        # PyPy2 5.10.0: Mean +- std dev: 3.24 us +- 0.17 us ->  1.5x

        # Compiling with Cython gets us to these numbers:
        # 3.6.4        : Mean +- std dev: 3.63 us +- 0.14 us
        # 2.7.14       : Mean +- std dev: 3.37 us +- 0.20 us
        # PyPy2 5.10.0 : Mean +- std dev: 4.44 us +- 0.28 us


        _greenlet__init__(self, None, get_hub())

        if run is not None:
            self._run = run

        # If they didn't pass a callable at all, then they must
        # already have one. Note that subclassing to override the run() method
        # itself has never been documented or supported.
        if not callable(self._run):
            raise TypeError("The run argument or self._run must be callable")

        self.args = args
        self.kwargs = kwargs
        self.value = None

        #: An event, such as a timer or a callback that fires. It is established in
        #: start() and start_later() as those two objects, respectively.
        #: Once this becomes non-None, the Greenlet cannot be started again. Conversely,
        #: kill() and throw() check for non-None to determine if this object has ever been
        #: scheduled for starting. A placeholder _dummy_event is assigned by them to prevent
        #: the greenlet from being started in the future, if necessary.
        self._start_event = None

        self._notifier = None
        self._formatted_info = None
        self._links = []
        self._ident = None

        # Initial state: None.
        # Completed successfully: (None, None, None)
        # Failed with exception: (t, v, dump_traceback(tb)))
        self._exc_info = None

        if GEVENT_CONFIG.track_greenlet_tree:
            spawner = getcurrent() # pylint:disable=undefined-variable
            self.spawning_greenlet = wref(spawner)
            try:
                self.spawn_tree_locals = spawner.spawn_tree_locals
            except AttributeError:
                self.spawn_tree_locals = {}
                if spawner.parent is not None:
                    # The main greenlet has no parent.
                    # Its children get separate locals.
                    spawner.spawn_tree_locals = self.spawn_tree_locals

            self._spawning_stack_frames = _extract_stack(self.spawning_stack_limit)
            self._spawning_stack_frames.extend(getattr(spawner, '_spawning_stack_frames', []))
        else:
            # None is the default for all of these in Cython, but we
            # need to declare them for pure-Python mode.
            self.spawning_greenlet = None
            self.spawn_tree_locals = None
            self._spawning_stack_frames = None
示例#36
0
def cancel_wait(watcher, error=cancel_wait_ex):
    """See :meth:`gevent.hub.Hub.cancel_wait`"""
    get_hub().cancel_wait(watcher, error)
示例#37
0
 def __call__(self, source):
     g = greenlet(self.callback, get_hub())
     g.switch(source)
示例#38
0
    def __init__(self, run=None, *args, **kwargs):
        """
        :param args: The arguments passed to the ``run`` function.
        :param kwargs: The keyword arguments passed to the ``run`` function.
        :keyword callable run: The callable object to run. If not given, this object's
            `_run` method will be invoked (typically defined by subclasses).

        .. versionchanged:: 1.1b1
            The ``run`` argument to the constructor is now verified to be a callable
            object. Previously, passing a non-callable object would fail after the greenlet
            was spawned.

        .. versionchanged:: 1.3b1
           The ``GEVENT_TRACK_GREENLET_TREE`` configuration value may be set to
           a false value to disable ``spawn_tree_locals``, ``spawning_greenlet``,
           and ``spawning_stack``. The first two will be None in that cases, and the
           latter will be empty.
        """
        # The attributes are documented in the .rst file

        # greenlet.greenlet(run=None, parent=None)
        # Calling it with both positional arguments instead of a keyword
        # argument (parent=get_hub()) speeds up creation of this object ~30%:
        # python -m timeit -s 'import gevent' 'gevent.Greenlet()'
        # Python 3.5: 2.70usec with keywords vs 1.94usec with positional
        # Python 3.4: 2.32usec with keywords vs 1.74usec with positional
        # Python 3.3: 2.55usec with keywords vs 1.92usec with positional
        # Python 2.7: 1.73usec with keywords vs 1.40usec with positional

        # Timings taken Feb 21 2018 prior to integration of #755
        # python -m perf timeit -s 'import gevent' 'gevent.Greenlet()'
        # 3.6.4       : Mean +- std dev: 1.08 us +- 0.05 us
        # 2.7.14      : Mean +- std dev: 1.44 us +- 0.06 us
        # PyPy2 5.10.0: Mean +- std dev: 2.14 ns +- 0.08 ns

        # After the integration of spawning_stack, spawning_greenlet,
        # and spawn_tree_locals on that same date:
        # 3.6.4       : Mean +- std dev: 8.92 us +- 0.36 us ->  8.2x
        # 2.7.14      : Mean +- std dev: 14.8 us +- 0.5 us  -> 10.2x
        # PyPy2 5.10.0: Mean +- std dev: 3.24 us +- 0.17 us ->  1.5x

        # Compiling with Cython gets us to these numbers:
        # 3.6.4        : Mean +- std dev: 3.63 us +- 0.14 us
        # 2.7.14       : Mean +- std dev: 3.37 us +- 0.20 us
        # PyPy2 5.10.0 : Mean +- std dev: 4.44 us +- 0.28 us

        _greenlet__init__(self, None, get_hub())

        if run is not None:
            self._run = run

        # If they didn't pass a callable at all, then they must
        # already have one. Note that subclassing to override the run() method
        # itself has never been documented or supported.
        if not callable(self._run):
            raise TypeError("The run argument or self._run must be callable")

        self.args = args
        self.kwargs = kwargs
        self.value = None

        #: An event, such as a timer or a callback that fires. It is established in
        #: start() and start_later() as those two objects, respectively.
        #: Once this becomes non-None, the Greenlet cannot be started again. Conversely,
        #: kill() and throw() check for non-None to determine if this object has ever been
        #: scheduled for starting. A placeholder _dummy_event is assigned by them to prevent
        #: the greenlet from being started in the future, if necessary.
        self._start_event = None

        self._notifier = None
        self._formatted_info = None
        self._links = []
        self._ident = None

        # Initial state: None.
        # Completed successfully: (None, None, None)
        # Failed with exception: (t, v, dump_traceback(tb)))
        self._exc_info = None

        if GEVENT_CONFIG.track_greenlet_tree:
            spawner = getcurrent()  # pylint:disable=undefined-variable
            self.spawning_greenlet = wref(spawner)
            try:
                self.spawn_tree_locals = spawner.spawn_tree_locals
            except AttributeError:
                self.spawn_tree_locals = {}
                if spawner.parent is not None:
                    # The main greenlet has no parent.
                    # Its children get separate locals.
                    spawner.spawn_tree_locals = self.spawn_tree_locals

            self._spawning_stack_frames = _extract_stack(
                self.spawning_stack_limit)
            self._spawning_stack_frames.extend(
                getattr(spawner, '_spawning_stack_frames', []))
        else:
            # None is the default for all of these in Cython, but we
            # need to declare them for pure-Python mode.
            self.spawning_greenlet = None
            self.spawn_tree_locals = None
            self._spawning_stack_frames = None
示例#39
0
 def __call__(self, source):
     g = greenlet(self.callback, get_hub())
     g.switch(source)
示例#40
0
def cancel_wait(watcher, error=cancel_wait_ex):
    """See :meth:`gevent.hub.Hub.cancel_wait`"""
    get_hub().cancel_wait(watcher, error)
示例#41
0
    def __wait_to_be_notified(self, rawlink):  # pylint:disable=too-many-branches
        # We've got to watch where we could potentially release the GIL.
        # Decisions we make based an the state of this object must be in blocks
        # that cannot release the GIL.
        resume_this_greenlet = None
        watcher = None
        current_hub = get_hub()
        send = None

        while 1:
            my_hub = self.hub
            if my_hub is current_hub:
                break

            # We're owned by another hub.
            if my_hub.dead:  # dead is a property, this could have released the GIL.
                # We have the GIL back. Did anything change?
                if my_hub is not self.hub:
                    continue  # start over.
                # The other hub is dead, so we can take ownership.
                self.hub = current_hub
                break
            # Some other hub owns this object. We must ask it to wake us
            # up. We can't use a Python-level ``Lock`` because
            # (1) it doesn't support a timeout on all platforms; and
            # (2) we don't want to block this hub from running. So we need to
            # do so in a way that cooperates with *two* hubs. That's what an
            # async watcher is built for.
            #
            # Allocating and starting the watcher *could* release the GIL.
            # with the libev corcext, allocating won't, but starting briefly will.
            # With other backends, allocating might, and starting might also.
            # So...XXX: Race condition here, tiny though it may be.
            watcher = current_hub.loop.async_()
            send = watcher.send_ignoring_arg
            if rawlink:
                # Make direct calls to self.rawlink, the most common case,
                # so cython can more easily optimize.
                self.rawlink(send)
            else:
                self._notifier.args[0].append(send)

            watcher.start(getcurrent().switch, self)  # pylint:disable=undefined-variable
            break

        if self.hub is current_hub:
            resume_this_greenlet = getcurrent().switch  # pylint:disable=undefined-variable
            if rawlink:
                self.rawlink(resume_this_greenlet)
            else:
                self._notifier.args[0].append(resume_this_greenlet)
        try:
            self._drop_lock_for_switch_out()
            result = current_hub.switch()  # Probably releases
            # If we got here, we were automatically unlinked already.
            resume_this_greenlet = None
            if result is not self:  # pragma: no cover
                raise InvalidSwitchError('Invalid switch into %s.wait(): %r' %
                                         (
                                             self.__class__.__name__,
                                             result,
                                         ))
        finally:
            self._acquire_lock_for_switch_in()
            self.__unlink_all(resume_this_greenlet)
            self.__unlink_all(send)
            if watcher is not None:
                watcher.stop()
                watcher.close()
示例#42
0
    def acquire(self, blocking=True, timeout=None):
        """
        acquire(blocking=True, timeout=None) -> bool

        Acquire the semaphore.

        .. note:: If this semaphore was initialized with a *value* of 0,
           this method will block forever (unless a timeout is given or blocking is
           set to false).

        :keyword bool blocking: If True (the default), this function will block
           until the semaphore is acquired.
        :keyword float timeout: If given, and *blocking* is true,
           specifies the maximum amount of seconds
           this method will block.
        :return: A `bool` indicating whether the semaphore was acquired.
           If ``blocking`` is True and ``timeout`` is None (the default), then
           (so long as this semaphore was initialized with a size greater than 0)
           this will always return True. If a timeout was given, and it expired before
           the semaphore was acquired, False will be returned. (Note that this can still
           raise a ``Timeout`` exception, if some other caller had already started a timer.)
        """
        # pylint:disable=too-many-return-statements,too-many-branches
        # Sadly, the body of this method is rather complicated.
        if self._multithreaded is _UNSET:
            self._multithreaded = self._get_thread_ident()
        elif self._multithreaded != self._get_thread_ident():
            self._multithreaded = _MULTI

        # We conceptually now belong to the hub of the thread that
        # called this, whether or not we have to block. Note that we
        # cannot force it to be created yet, because Semaphore is used
        # by importlib.ModuleLock which is used when importing the hub
        # itself! This also checks for cross-thread issues.
        invalid_thread_use = None
        try:
            self._capture_hub(False)
        except InvalidThreadUseError as e:
            # My hub belongs to some other thread. We didn't release the GIL/object lock
            # by raising the exception, so we know this is still true.
            invalid_thread_use = e.args
            e = None
            if not self.counter and blocking:
                # We would need to block. So coordinate with the main hub.
                return self.__acquire_from_other_thread(
                    invalid_thread_use, blocking, timeout)

        if self.counter > 0:
            self.counter -= 1
            return True

        if not blocking:
            return False

        if self._multithreaded is not _MULTI and self.hub is None:  # pylint:disable=access-member-before-definition
            self.hub = get_hub()  # pylint:disable=attribute-defined-outside-init

        if self.hub is None and not invalid_thread_use:
            # Someone else is holding us. There's not a hub here,
            # nor is there a hub in that thread. We'll need to use regular locks.
            # This will be unfair to yet a third thread that tries to use us with greenlets.
            return self.__acquire_from_other_thread(
                (None, None, self._getcurrent(), "NoHubs"), blocking, timeout)

        # self._wait may drop both the GIL and the _lock_lock.
        # By the time we regain control, both have been reacquired.
        try:
            success = self._wait(timeout)
        except LoopExit as ex:
            args = ex.args
            ex = None
            if self.counter:
                success = True
            else:
                # Avoid using ex.hub property to keep holding the GIL
                if len(args) == 3 and args[1].main_hub:
                    # The main hub, meaning the main thread. We probably can do nothing with this.
                    raise
                return self.__acquire_from_other_thread(
                    (self.hub, get_hub_if_exists(), self._getcurrent(),
                     "LoopExit"), blocking, timeout)

        if not success:
            assert timeout is not None
            # Our timer expired.
            return False

        # Neither our timer or another one expired, so we blocked until
        # awoke. Therefore, the counter is ours
        assert self.counter > 0, (
            self.counter,
            blocking,
            timeout,
            success,
        )
        self.counter -= 1
        return True
示例#43
0
 def __init__(self, hub=None):
     self.hub = get_hub() if hub is None else hub
     self.greenlet = None
     self.value = None
     self._exception = _NONE
示例#44
0
    def __init__(self, run=None, *args, **kwargs):
        """
        :param args: The arguments passed to the ``run`` function.
        :param kwargs: The keyword arguments passed to the ``run`` function.
        :keyword callable run: The callable object to run. If not given, this object's
            `_run` method will be invoked (typically defined by subclasses).

        .. versionchanged:: 1.1b1
            The ``run`` argument to the constructor is now verified to be a callable
            object. Previously, passing a non-callable object would fail after the greenlet
            was spawned.

        .. versionchanged:: 1.3b1
           The ``GEVENT_TRACK_GREENLET_TREE`` configuration value may be set to
           a false value to disable ``spawn_tree_locals``, ``spawning_greenlet``,
           and ``spawning_stack``. The first two will be None in that case, and the
           latter will be empty.
        """
        # The attributes are documented in the .rst file

        # greenlet.greenlet(run=None, parent=None)
        # Calling it with both positional arguments instead of a keyword
        # argument (parent=get_hub()) speeds up creation of this object ~30%:
        # python -m timeit -s 'import gevent' 'gevent.Greenlet()'
        # Python 3.5: 2.70usec with keywords vs 1.94usec with positional
        # Python 3.4: 2.32usec with keywords vs 1.74usec with positional
        # Python 3.3: 2.55usec with keywords vs 1.92usec with positional
        # Python 2.7: 1.73usec with keywords vs 1.40usec with positional

        # Timings taken Feb 21 2018 prior to integration of #755
        # python -m perf timeit -s 'import gevent' 'gevent.Greenlet()'
        # 3.6.4       : Mean +- std dev: 1.08 us +- 0.05 us
        # 2.7.14      : Mean +- std dev: 1.44 us +- 0.06 us
        # PyPy2 5.10.0: Mean +- std dev: 2.14 ns +- 0.08 ns

        # After the integration of spawning_stack, spawning_greenlet,
        # and spawn_tree_locals on that same date:
        # 3.6.4       : Mean +- std dev: 8.92 us +- 0.36 us ->  8.2x
        # 2.7.14      : Mean +- std dev: 14.8 us +- 0.5 us  -> 10.2x
        # PyPy2 5.10.0: Mean +- std dev: 3.24 us +- 0.17 us ->  1.5x

        # Compiling with Cython gets us to these numbers:
        # 3.6.4        : Mean +- std dev: 3.63 us +- 0.14 us
        # 2.7.14       : Mean +- std dev: 3.37 us +- 0.20 us
        # PyPy2 5.10.0 : Mean +- std dev: 4.44 us +- 0.28 us


        _greenlet__init__(self, None, get_hub())

        if run is not None:
            self._run = run

        # If they didn't pass a callable at all, then they must
        # already have one. Note that subclassing to override the run() method
        # itself has never been documented or supported.
        if not callable(self._run):
            raise TypeError("The run argument or self._run must be callable")

        self.args = args
        self.kwargs = kwargs
        self.value = None

        #: An event, such as a timer or a callback that fires. It is established in
        #: start() and start_later() as those two objects, respectively.
        #: Once this becomes non-None, the Greenlet cannot be started again. Conversely,
        #: kill() and throw() check for non-None to determine if this object has ever been
        #: scheduled for starting. A placeholder _dummy_event is assigned by them to prevent
        #: the greenlet from being started in the future, if necessary.
        self._start_event = None

        self._notifier = None
        self._formatted_info = None
        self._links = []
        self._ident = None

        # Initial state: None.
        # Completed successfully: (None, None, None)
        # Failed with exception: (t, v, dump_traceback(tb)))
        self._exc_info = None

        if GEVENT_CONFIG.track_greenlet_tree:
            spawner = getcurrent() # pylint:disable=undefined-variable
            self.spawning_greenlet = wref(spawner)
            try:
                self.spawn_tree_locals = spawner.spawn_tree_locals
            except AttributeError:
                self.spawn_tree_locals = {}
                if spawner.parent is not None:
                    # The main greenlet has no parent.
                    # Its children get separate locals.
                    spawner.spawn_tree_locals = self.spawn_tree_locals

            self._spawning_stack_frames = _extract_stack(self.spawning_stack_limit)
            self._spawning_stack_frames.extend(getattr(spawner, '_spawning_stack_frames', []))
        else:
            # None is the default for all of these in Cython, but we
            # need to declare them for pure-Python mode.
            self.spawning_greenlet = None
            self.spawn_tree_locals = None
            self._spawning_stack_frames = None