summaryrefslogtreecommitdiff
path: root/eventlet/pools.py
diff options
context:
space:
mode:
authorRyan Williams <rdw@lindenlab.com>2010-02-21 22:31:23 -0500
committerRyan Williams <rdw@lindenlab.com>2010-02-21 22:31:23 -0500
commit13f199da00461a9fa5b77bab4ed91918bcddcc95 (patch)
treefa1f212e863e99927b64e3e43e32e8f4eca5e143 /eventlet/pools.py
parent2466add6fa7d086c6a6fc3b9e6e0c8c3585ea2d0 (diff)
downloadeventlet-13f199da00461a9fa5b77bab4ed91918bcddcc95.tar.gz
Improved docs on pools for ericflo, fixes #40.
Diffstat (limited to 'eventlet/pools.py')
-rw-r--r--eventlet/pools.py89
1 files changed, 57 insertions, 32 deletions
diff --git a/eventlet/pools.py b/eventlet/pools.py
index d79f7f3..73d8238 100644
--- a/eventlet/pools.py
+++ b/eventlet/pools.py
@@ -34,35 +34,41 @@ except ImportError:
class Pool(object):
"""
- Pool is a base class that is meant to be subclassed. When subclassing,
- define the :meth:`create` method to implement the desired resource.
+ Pool is a base class that implements resource limitation and construction.
+ It is meant to be subclassed. When subclassing, define only
+ the :meth:`create` method to implement the desired resource::
- When using the pool, if you do a get, you should **always** do a
- :meth:`put`.
-
- The pattern is::
-
- thing = self.pool.get()
- try:
- thing.method()
- finally:
- self.pool.put(thing)
-
- The maximum size of the pool can be modified at runtime via the
- :attr:`max_size` attribute. Adjusting this number does not affect existing
- items checked out of the pool, nor on any waiters who are waiting for an
- item to free up. Some indeterminate number of :meth:`get`/:meth:`put`
- cycles will be necessary before the new maximum size truly matches the
- actual operation of the pool.
+ class MyPool(pools.Pool):
+ def create(self):
+ return MyObject()
+
+ If using 2.5 or greater, the :meth:`item` method acts as a context manager;
+ that's the best way to use it::
+
+ with mypool.item() as thing:
+ thing.dostuff()
+
+ If stuck on 2.4, the :meth:`get` and :meth:`put` methods are the preferred
+ nomenclature. Use a ``finally`` to ensure that nothing is leaked::
+
+ thing = self.pool.get()
+ try:
+ thing.dostuff()
+ finally:
+ self.pool.put(thing)
+
+ The maximum size of the pool can be modified at runtime via
+ the :meth:`resize` method.
+
+ Specifying a non-zero *min-size* argument pre-populates the pool with
+ *min_size* items. *max-size* sets a hard limit to the size of the pool --
+ it cannot contain any more items than *max_size*, and if there are already
+ *max_size* items 'checked out' of the pool, the pool will cause any
+ greenthread calling :meth:`get` to cooperatively yield until an item
+ is :meth:`put` in.
"""
def __init__(self, min_size=0, max_size=4, order_as_stack=False):
- """ Pre-populates the pool with *min_size* items. Sets a hard limit to
- the size of the pool -- it cannot contain any more items than
- *max_size*, and if there are already *max_size* items 'checked out' of
- the pool, the pool will cause any getter to cooperatively yield until an
- item is put in.
-
- *order_as_stack* governs the ordering of the items in the free pool.
+ """*order_as_stack* governs the ordering of the items in the free pool.
If ``False`` (the default), the free items collection (of items that
were created and were put back in the pool) acts as a round-robin,
giving each item approximately equal utilization. If ``True``, the
@@ -80,7 +86,8 @@ class Pool(object):
self.free_items.append(self.create())
def get(self):
- """Return an item from the pool, when one is available
+ """Return an item from the pool, when one is available. This may
+ cause the calling greenthread to block.
"""
if self.free_items:
return self.free_items.popleft()
@@ -89,12 +96,13 @@ class Pool(object):
self.current_size += 1
return created
return self.channel.get()
-
+
if item_impl is not None:
item = item_impl
def put(self, item):
- """Put an item back into the pool, when done
+ """Put an item back into the pool, when done. This may
+ cause the putting greenthread to block.
"""
if self.current_size > self.max_size:
self.current_size -= 1
@@ -109,12 +117,19 @@ class Pool(object):
self.free_items.append(item)
def resize(self, new_size):
- """Resize the pool
+ """Resize the pool to *new_size*.
+
+ Adjusting this number does not affect existing items checked out of
+ the pool, nor on any greenthreads who are waiting for an item to free
+ up. Some indeterminate number of :meth:`get`/:meth:`put`
+ cycles will be necessary before the new maximum size truly matches
+ the actual operation of the pool.
"""
self.max_size = new_size
def free(self):
- """Return the number of free items in the pool.
+ """Return the number of free items in the pool. This corresponds
+ to the number of :meth:`get` calls needed to empty the pool.
"""
return len(self.free_items) + self.max_size - self.current_size
@@ -124,7 +139,17 @@ class Pool(object):
return max(0, self.channel.getting() - self.channel.putting())
def create(self):
- """Generate a new pool item
+ """Generate a new pool item. This method must be overridden in order
+ for the pool to function. It accepts no arguments and returns a single
+ instance of whatever thing the pool is supposed to contain.
+
+ In general, :meth:`create` is called whenever the pool exceeds its
+ previous high-water mark of concurrently-checked-out-items. In other
+ words, in a new pool with *min_size* of 0, the very first call
+ to :meth:`get` will result in a call to :meth:`create`. If the first
+ caller calls :meth:`put` before some other caller calls :meth:`get`,
+ then the first item will be returned, and :meth:`create` will not be
+ called a second time.
"""
raise NotImplementedError("Implement in subclass")