Commit 778b8f44 authored by Jason Madden's avatar Jason Madden

Documentation cleanups and add timeouts to Pool.start.

parent 5aa4bb80
...@@ -464,10 +464,14 @@ class Group(GroupMappingMixin): ...@@ -464,10 +464,14 @@ class Group(GroupMappingMixin):
def add(self, greenlet): def add(self, greenlet):
""" """
Begin tracking the greenlet. Begin tracking the *greenlet*.
If this group is :meth:`full`, then this method may block If this group is :meth:`full`, then this method may block
until it is possible to track the greenlet. until it is possible to track the greenlet.
Typically the *greenlet* should **not** be started when
it is added because if this object blocks in this method,
then the *greenlet* may run to completion before it is tracked.
""" """
try: try:
rawlink = greenlet.rawlink rawlink = greenlet.rawlink
...@@ -498,8 +502,8 @@ class Group(GroupMappingMixin): ...@@ -498,8 +502,8 @@ class Group(GroupMappingMixin):
def start(self, greenlet): def start(self, greenlet):
""" """
Start the un-started *greenlet* and add it to the collection of greenlets Add the **unstarted** *greenlet* to the collection of greenlets
this group is monitoring. this group is monitoring, nd then start it.
""" """
self.add(greenlet) self.add(greenlet)
greenlet.start() greenlet.start()
...@@ -722,24 +726,46 @@ class Pool(Group): ...@@ -722,24 +726,46 @@ class Pool(Group):
return 1 return 1
return max(0, self.size - len(self)) return max(0, self.size - len(self))
def add(self, greenlet, blocking=True, timeout=None): def start(self, greenlet, *args, **kwargs): # pylint:disable=arguments-differ
"""
start(greenlet, blocking=True, timeout=None) -> None
Add the **unstarted** *greenlet* to the collection of greenlets
this group is monitoring and then start it.
Parameters are as for :meth:`add`.
""" """
Begin tracking the given greenlet, possibly blocking until space is self.add(greenlet, *args, **kwargs)
available. greenlet.start()
def add(self, greenlet, blocking=True, timeout=None): # pylint:disable=arguments-differ
"""
Begin tracking the given **unstarted** greenlet, possibly blocking
until space is available.
Usually you should call :meth:`start` to track and start the greenlet
instead of using this lower-level method.
:keyword bool blocking: If True (the default), this function will block :keyword bool blocking: If True (the default), this function
until the pool has space or a timeout occurs. If False, this function will block until the pool has space or a timeout occurs. If
will immediately raise a Timeout if the pool is currently full. False, this function will immediately raise a Timeout if the
:keyword float timeout: The maximum number of seconds this method will pool is currently full.
block, if ``blocking`` is True. (Ignored if ``blocking`` is False.) :keyword float timeout: The maximum number of seconds this
method will block, if ``blocking`` is True. (Ignored if
``blocking`` is False.)
:raises PoolFull: if either ``blocking`` is False and the pool
was full, or if ``blocking`` is True and ``timeout`` was
exceeded.
Raises `PoolFull` if either ``blocking`` is False and the pool was full, .. caution:: If the *greenlet* has already been started and
or if ``blocking`` is True and ``timeout`` was exceeded. *blocking* is true, then the greenlet may run to completion
while the current greenlet blocks waiting to track it. This would
enable higher concurrency than desired.
.. seealso:: :meth:`Group.add` .. seealso:: :meth:`Group.add`
.. versionchanged:: 1.3.0 .. versionchanged:: 1.3.0 Added the ``blocking`` and
Added the ``blocking`` and ```timeout`` parameters. ``timeout`` parameters.
""" """
if not self._semaphore.acquire(blocking=blocking, timeout=timeout): if not self._semaphore.acquire(blocking=blocking, timeout=timeout):
# We failed to acquire the semaphore. # We failed to acquire the semaphore.
......
...@@ -205,6 +205,7 @@ class PoolBasicTests(greentest.TestCase): ...@@ -205,6 +205,7 @@ class PoolBasicTests(greentest.TestCase):
finally: finally:
first.kill() first.kill()
@greentest.ignores_leakcheck
def test_add_method_non_blocking(self): def test_add_method_non_blocking(self):
p = self.klass(size=1) p = self.klass(size=1)
first = gevent.spawn(gevent.sleep, 1000) first = gevent.spawn(gevent.sleep, 1000)
...@@ -219,6 +220,7 @@ class PoolBasicTests(greentest.TestCase): ...@@ -219,6 +220,7 @@ class PoolBasicTests(greentest.TestCase):
finally: finally:
first.kill() first.kill()
@greentest.ignores_leakcheck
def test_add_method_timeout(self): def test_add_method_timeout(self):
p = self.klass(size=1) p = self.klass(size=1)
first = gevent.spawn(gevent.sleep, 1000) first = gevent.spawn(gevent.sleep, 1000)
...@@ -233,6 +235,21 @@ class PoolBasicTests(greentest.TestCase): ...@@ -233,6 +235,21 @@ class PoolBasicTests(greentest.TestCase):
finally: finally:
first.kill() first.kill()
@greentest.ignores_leakcheck
def test_start_method_timeout(self):
p = self.klass(size=1)
first = gevent.spawn(gevent.sleep, 1000)
try:
second = gevent.Greenlet(gevent.sleep, 1000)
try:
p.add(first)
with self.assertRaises(pool.PoolFull):
p.start(second, timeout=0.100)
finally:
second.kill()
finally:
first.kill()
def test_apply(self): def test_apply(self):
p = self.klass() p = self.klass()
result = p.apply(lambda a: ('foo', a), (1, )) result = p.apply(lambda a: ('foo', a), (1, ))
......
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