Commit 5da86fd5 authored by Jason Madden's avatar Jason Madden

Clarify documentation for Group.join and Event. Also a TODO comment about...

Clarify documentation for Group.join and Event. Also a TODO comment about Event vs AsyncResult. [skip ci]
parent d96b2a21
...@@ -20,9 +20,22 @@ class Event(object): ...@@ -20,9 +20,22 @@ class Event(object):
An event object manages an internal flag that can be set to true with the An event object manages an internal flag that can be set to true with the
:meth:`set` method and reset to false with the :meth:`clear` method. The :meth:`wait` method :meth:`set` method and reset to false with the :meth:`clear` method. The :meth:`wait` method
blocks until the flag is true. blocks until the flag is true.
.. note::
The order and timing in which waiting greenlets are awakened is not determined.
As an implementation note, in gevent 1.1 and 1.0, waiting greenlets are awakened in a
undetermined order sometime *after* the current greenlet yields to the event loop. Other greenlets
(those not waiting to be awakened) may run between the current greenlet yielding and
the waiting greenlets being awakened. These details may change in the future.
""" """
def __init__(self): def __init__(self):
# XXX: TODO: AsyncResult guarantees the order that waiting
# greenlets are called by using a deque(), and also doesn't
# make a copy (_todo). Should we use a deque? Should
# AsyncResult copy? It seems we should be consistent. And if
# we did, we could share a great deal of the common code in
# that case.
self._links = set() self._links = set()
self._todo = set() self._todo = set()
self._flag = False self._flag = False
...@@ -43,9 +56,10 @@ class Event(object): ...@@ -43,9 +56,10 @@ class Event(object):
""" """
Set the internal flag to true. Set the internal flag to true.
All greenlets waiting for it to become true are awakened. All greenlets waiting for it to become true are awakened in
Greenlets that call :meth:`wait` once the flag is true will some order at some time in the future. Greenlets that call
not block at all. :meth:`wait` once the flag is true will not block at all
(until :meth:`clear` is called).
""" """
self._flag = True self._flag = True
self._todo.update(self._links) self._todo.update(self._links)
...@@ -62,10 +76,11 @@ class Event(object): ...@@ -62,10 +76,11 @@ class Event(object):
self._flag = False self._flag = False
def wait(self, timeout=None): def wait(self, timeout=None):
"""Block until the internal flag is true. """
Block until the internal flag is true.
If the internal flag is true on entry, return immediately. Otherwise, If the internal flag is true on entry, return immediately. Otherwise,
block until another thread calls :meth:`set` to set the flag to true, block until another thread (greenlet) calls :meth:`set` to set the flag to true,
or until the optional timeout occurs. or until the optional timeout occurs.
When the *timeout* argument is present and not ``None``, it should be a When the *timeout* argument is present and not ``None``, it should be a
......
...@@ -494,9 +494,24 @@ class Group(GroupMappingMixin): ...@@ -494,9 +494,24 @@ class Group(GroupMappingMixin):
def join(self, timeout=None, raise_error=False): def join(self, timeout=None, raise_error=False):
""" """
Wait for the group to become empty at least once. Note that by the Wait for this group to become empty *at least once*.
time the waiting code runs again, some other greenlet may have been
added. If there are no greenlets in the group, returns immediately.
.. note:: By the time the waiting code (the caller of this
method) regains control, a greenlet may have been added to
this group, and so this object may no longer be empty. (That
is, ``group.join(); assert len(group) == 0`` is not
guaranteed to hold.) This method only guarantees that the group
reached a ``len`` of 0 at some point.
:keyword bool raise_error: If True (*not* the default), if any
greenlet that finished while the join was in progress raised
an exception, that exception will be raised to the caller of
this method. If multiple greenlets raised exceptions, which
one gets re-raised is not determined. Only greenlets currently
in the group when this method is called are guaranteed to
be checked for exceptions.
""" """
if raise_error: if raise_error:
greenlets = self.greenlets.copy() greenlets = self.greenlets.copy()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment