Added getting() and putting() methods to the Queue class, replaced coros.queue with queue.Queue in pools.py.

This commit is contained in:
Ryan Williams
2010-01-23 20:57:42 -05:00
parent de57fcd8ab
commit 66ea48836d
3 changed files with 32 additions and 17 deletions

View File

@@ -1,7 +1,7 @@
import collections import collections
from eventlet import api from eventlet import api
from eventlet import coros from eventlet import queue
__all__ = ['Pool', 'TokenPool'] __all__ = ['Pool', 'TokenPool']
@@ -74,7 +74,7 @@ class Pool(object):
self.max_size = max_size self.max_size = max_size
self.order_as_stack = order_as_stack self.order_as_stack = order_as_stack
self.current_size = 0 self.current_size = 0
self.channel = coros.queue(0) self.channel = queue.LightQueue(0)
self.free_items = collections.deque() self.free_items = collections.deque()
for x in xrange(min_size): for x in xrange(min_size):
self.current_size += 1 self.current_size += 1
@@ -89,7 +89,7 @@ class Pool(object):
created = self.create() created = self.create()
self.current_size += 1 self.current_size += 1
return created return created
return self.channel.wait() return self.channel.get()
if item_impl is not None: if item_impl is not None:
item = item_impl item = item_impl
@@ -102,7 +102,7 @@ class Pool(object):
return return
if self.waiting(): if self.waiting():
self.channel.send(item) self.channel.put(item)
else: else:
if self.order_as_stack: if self.order_as_stack:
self.free_items.appendleft(item) self.free_items.appendleft(item)
@@ -122,7 +122,7 @@ class Pool(object):
def waiting(self): def waiting(self):
"""Return the number of routines waiting for a pool item. """Return the number of routines waiting for a pool item.
""" """
return self.channel.waiting() return max(0, self.channel.getting() - self.channel.putting())
def create(self): def create(self):
"""Generate a new pool item """Generate a new pool item

View File

@@ -1,13 +1,22 @@
# Copyright (c) 2009 Denis Bilenko. See LICENSE for details. # Copyright (c) 2009 Denis Bilenko. See LICENSE for details.
"""Synchronized queues. """Synchronized queues.
The :mod:`eventlet.queue` module implements multi-producer, multi-consumer queues that work across greenlets, with the API similar to the classes found in the standard :mod:`Queue` and :class:`multiprocessing <multiprocessing.Queue>` modules. The :mod:`eventlet.queue` module implements multi-producer, multi-consumer
queues that work across greenlets, with the API similar to the classes found in
the standard :mod:`Queue` and :class:`multiprocessing <multiprocessing.Queue>`
modules.
A major difference is that queues in this module operate as channels when A major difference is that queues in this module operate as channels when
initialized with *maxsize* of zero. In such case, both :meth:`Queue.empty` initialized with *maxsize* of zero. In such case, both :meth:`Queue.empty`
and :meth:`Queue.full` return ``True`` and :meth:`Queue.put` always blocks until a call to :meth:`Queue.get` retrieves the item. and :meth:`Queue.full` return ``True`` and :meth:`Queue.put` always blocks until
a call to :meth:`Queue.get` retrieves the item.
Another interesting difference is that :meth:`Queue.qsize`, :meth:`Queue.empty`, and :meth:`Queue.full` *can* be used as indicators of whether the subsequent :meth:`Queue.get` or :meth:`Queue.put` will not block. An interesting difference, made possible because of greenthreads, is
that :meth:`Queue.qsize`, :meth:`Queue.empty`, and :meth:`Queue.full` *can* be
used as indicators of whether the subsequent :meth:`Queue.get`
or :meth:`Queue.put` will not block. The new methods :meth:`Queue.getting`
and :meth:`Queue.putting` report on the number of greenthreads blocking
in :meth:`put <Queue.put>` or :meth:`get <Queue.get>` respectively.
""" """
import sys import sys
@@ -149,6 +158,16 @@ class LightQueue(object):
def qsize(self): def qsize(self):
"""Return the size of the queue.""" """Return the size of the queue."""
return len(self.queue) return len(self.queue)
def putting(self):
"""Returns the number of greenthreads that are blocked waiting to put
items into the queue."""
return len(self.putters)
def getting(self):
"""Returns the number of greenthreads that are blocked waiting on an
empty queue."""
return len(self.getters)
def empty(self): def empty(self):
"""Return ``True`` if the queue is empty, ``False`` otherwise.""" """Return ``True`` if the queue is empty, ``False`` otherwise."""

View File

@@ -138,16 +138,15 @@ class TestQueue(LimitedTestCase):
self.assertEquals(q.get(), 'sent') self.assertEquals(q.get(), 'sent')
def test_waiting(self): def test_waiting(self):
return # TODO add this to the new queue
q = eventlet.Queue() q = eventlet.Queue()
gt1 = eventlet.spawn(q.get) gt1 = eventlet.spawn(q.get)
eventlet.sleep(0) eventlet.sleep(0)
self.assertEquals(1, q.waiting()) self.assertEquals(1, q.getting())
q.put('hi') q.put('hi')
eventlet.sleep(0) eventlet.sleep(0)
self.assertEquals(0, q.waiting()) self.assertEquals(0, q.getting())
self.assertEquals('hi', gt1.wait()) self.assertEquals('hi', gt1.wait())
self.assertEquals(0, q.waiting()) self.assertEquals(0, q.getting())
def test_channel_send(self): def test_channel_send(self):
channel = eventlet.Queue(0) channel = eventlet.Queue(0)
@@ -194,18 +193,15 @@ class TestQueue(LimitedTestCase):
w2 = eventlet.spawn(c.get) w2 = eventlet.spawn(c.get)
w3 = eventlet.spawn(c.get) w3 = eventlet.spawn(c.get)
eventlet.sleep(0) eventlet.sleep(0)
# TODO add waiting method to queue self.assertEquals(c.getting(), 3)
#self.assertEquals(c.waiting(), 3)
s1 = eventlet.spawn(c.put, 1) s1 = eventlet.spawn(c.put, 1)
s2 = eventlet.spawn(c.put, 2) s2 = eventlet.spawn(c.put, 2)
s3 = eventlet.spawn(c.put, 3) s3 = eventlet.spawn(c.put, 3)
eventlet.sleep(0) # this gets all the sends into a waiting state
# TODO add waiting method to queue
#self.assertEquals(c.waiting(), 0)
s1.wait() s1.wait()
s2.wait() s2.wait()
s3.wait() s3.wait()
self.assertEquals(c.getting(), 0)
# NOTE: we don't guarantee that waiters are served in order # NOTE: we don't guarantee that waiters are served in order
results = sorted([w1.wait(), w2.wait(), w3.wait()]) results = sorted([w1.wait(), w2.wait(), w3.wait()])
self.assertEquals(results, [1,2,3]) self.assertEquals(results, [1,2,3])