Пример #1
0
    def test_resize(self):
        pool = GreenPool(2)
        evt = Event()

        def wait_long_time(e):
            e.wait()

        pool.spawn(wait_long_time, evt)
        pool.spawn(wait_long_time, evt)
        self.assertEquals(pool.free(), 0)
        self.assert_pool_has_free(pool, 0)

        # verify that the pool discards excess items put into it
        pool.resize(1)

        # cause the wait_long_time functions to return, which will
        # trigger puts to the pool
        evt.send(None)
        sleep(0)
        sleep(0)

        self.assertEquals(pool.free(), 1)
        self.assert_pool_has_free(pool, 1)

        # resize larger and assert that there are more free items
        pool.resize(2)
        self.assertEquals(pool.free(), 2)
        self.assert_pool_has_free(pool, 2)
Пример #2
0
    def assert_pool_has_free(self, pool, num_free):
        self.assertEquals(pool.free(), num_free)

        def wait_long_time(e):
            e.wait()

        timer = Timeout(1)
        try:
            evt = Event()
            for x in xrange(num_free):
                pool.spawn(wait_long_time, evt)
                # if the pool has fewer free than we expect,
                # then we'll hit the timeout error
        finally:
            timer.cancel()

        # if the runtime error is not raised it means the pool had
        # some unexpected free items
        timer = Timeout(0, RuntimeError)
        try:
            self.assertRaises(RuntimeError, pool.spawn, wait_long_time, evt)
        finally:
            timer.cancel()

        # clean up by causing all the wait_long_time functions to return
        evt.send(None)
        sleep(0)
        sleep(0)
Пример #3
0
    def test_waiting(self):
        pool = GreenPool(1)
        done = Event()

        def consume():
            done.wait()

        def waiter(pool):
            evt = pool.spawn(consume)
            evt.wait()

        waiters = []
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 0)
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 1)
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 2)
        done.send(None)
        for w in waiters:
            w.wait()
        self.assertEqual(pool.waiting(), 0)
Пример #4
0
    def test_waiting(self):
        pool = GreenPool(1)
        done = Event()

        def consume():
            done.wait()

        def waiter(pool):
            evt = pool.spawn(consume)
            evt.wait()

        waiters = []
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 0)
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 1)
        waiters.append(spawn(waiter, pool))
        sleep(0)
        self.assertEqual(pool.waiting(), 2)
        done.send(None)
        for w in waiters:
            w.wait()
        self.assertEqual(pool.waiting(), 0)
Пример #5
0
    def test_resize(self):
        pool = GreenPool(2)
        evt = Event()

        def wait_long_time(e):
            e.wait()

        pool.spawn(wait_long_time, evt)
        pool.spawn(wait_long_time, evt)
        self.assertEquals(pool.free(), 0)
        self.assert_pool_has_free(pool, 0)

        # verify that the pool discards excess items put into it
        pool.resize(1)

        # cause the wait_long_time functions to return, which will
        # trigger puts to the pool
        evt.send(None)
        sleep(0)
        sleep(0)

        self.assertEquals(pool.free(), 1)
        self.assert_pool_has_free(pool, 1)

        # resize larger and assert that there are more free items
        pool.resize(2)
        self.assertEquals(pool.free(), 2)
        self.assert_pool_has_free(pool, 2)
Пример #6
0
    def assert_pool_has_free(self, pool, num_free):
        self.assertEquals(pool.free(), num_free)

        def wait_long_time(e):
            e.wait()

        timer = Timeout(1)
        try:
            evt = Event()
            for x in xrange(num_free):
                pool.spawn(wait_long_time, evt)
                # if the pool has fewer free than we expect,
                # then we'll hit the timeout error
        finally:
            timer.cancel()

        # if the runtime error is not raised it means the pool had
        # some unexpected free items
        timer = Timeout(0, RuntimeError)
        try:
            self.assertRaises(RuntimeError, pool.spawn, wait_long_time, evt)
        finally:
            timer.cancel()

        # clean up by causing all the wait_long_time functions to return
        evt.send(None)
        sleep(0)
        sleep(0)
Пример #7
0
    def test_double_exception (self):
        evt = Event()
        # send an exception through the event
        evt.send(exc = RuntimeError('from test_double_exception'))
        self.assertRaises(RuntimeError, evt.wait)
        evt.reset()

        # shouldn't see the RuntimeError again
        Timeout(0.001)
        self.assertRaises(Timeout, evt.wait)
Пример #8
0
    def test_send_exc (self):
        log = []
        e = Event()
        d = Event()

        def waiter ():
            try:
                result = e.wait()
                log.append(('received', result))
            except Exception, ex:
                log.append(('catched', ex))
            d.send()
Пример #9
0
    def _test_multiple_waiters (self, exception):
        evt = Event()
        value = 'some stuff'
        results = []

        def wait_on_event (i_am_done):
            evt.wait()
            results.append(True)
            i_am_done.send()
            if exception:
                raise Exception()

        waiters = []
        count = 5
        for i in range(count):
            waiters.append(Event())
            spawn_n(wait_on_event, waiters[-1])
        sleep()  # allow spawns to start executing
        evt.send()

        for w in waiters:
            w.wait()

        self.assertEqual(len(results), count)
Пример #10
0
class Queue(LightQueue):
    """
    Create a queue object with a given maximum size.

    If *maxsize* is less than zero or ``None``, the queue size is infinite.

    ``Queue(0)`` is a channel, that is, its :meth:`put` method always blocks 
    until the item is delivered. (This is unlike the standard :class:`Queue`, 
    where 0 means infinite size).
    
    In all other respects, this Queue class resembled the standard library,
    :class:`Queue`.
    """
    def __init__(self, maxsize=None):
        LightQueue.__init__(self, maxsize)
        self.unfinished_tasks = 0
        self._cond = Event()

    def _format(self):
        result = LightQueue._format(self)
        if self.unfinished_tasks:
            result += ' tasks=%s _cond=%s' % (self.unfinished_tasks,
                                              self._cond)
        return result

    def _put(self, item):
        LightQueue._put(self, item)
        self._put_bookkeeping()

    def _put_bookkeeping(self):
        self.unfinished_tasks += 1
        if self._cond.ready():
            self._cond.reset()

    def task_done(self):
        """
        Indicate that a formerly enqueued task is complete. Used by queue consumer threads.
        For each :meth:`get <Queue.get>` used to fetch a task, a subsequent call to :meth:`task_done` tells the queue
        that the processing on the task is complete.

        If a :meth:`join` is currently blocking, it will resume when all items have been processed
        (meaning that a :meth:`task_done` call was received for every item that had been
        :meth:`put <Queue.put>` into the queue).

        Raises a :exc:`ValueError` if called more times than there were items placed in the queue.
        """

        if self.unfinished_tasks <= 0:
            raise ValueError('task_done() called too many times')
        self.unfinished_tasks -= 1
        if self.unfinished_tasks == 0:
            self._cond.send(None)

    def join(self):
        """
        Block until all items in the queue have been gotten and processed.

        The count of unfinished tasks goes up whenever an item is added to the queue.
        The count goes down whenever a consumer thread calls :meth:`task_done` to indicate
        that the item was retrieved and all work on it is complete. When the count of
        unfinished tasks drops to zero, :meth:`join` unblocks.
        """
        return self._cond.wait()
Пример #11
0
class Queue(LightQueue):
    """
    Create a queue object with a given maximum size.

    If *maxsize* is less than zero or ``None``, the queue size is infinite.

    ``Queue(0)`` is a channel, that is, its :meth:`put` method always blocks 
    until the item is delivered. (This is unlike the standard :class:`Queue`, 
    where 0 means infinite size).
    
    In all other respects, this Queue class resembled the standard library,
    :class:`Queue`.
    """

    def __init__ (self, maxsize = None):
        LightQueue.__init__(self, maxsize)
        self.unfinished_tasks = 0
        self._cond = Event()

    def _format (self):
        result = LightQueue._format(self)
        if self.unfinished_tasks:
            result += ' tasks=%s _cond=%s' % (self.unfinished_tasks, self._cond)
        return result

    def _put (self, item):
        LightQueue._put(self, item)
        self._put_bookkeeping()

    def _put_bookkeeping (self):
        self.unfinished_tasks += 1
        if self._cond.ready():
            self._cond.reset()

    def task_done (self):
        """
        Indicate that a formerly enqueued task is complete. Used by queue consumer threads.
        For each :meth:`get <Queue.get>` used to fetch a task, a subsequent call to :meth:`task_done` tells the queue
        that the processing on the task is complete.

        If a :meth:`join` is currently blocking, it will resume when all items have been processed
        (meaning that a :meth:`task_done` call was received for every item that had been
        :meth:`put <Queue.put>` into the queue).

        Raises a :exc:`ValueError` if called more times than there were items placed in the queue.
        """

        if self.unfinished_tasks <= 0:
            raise ValueError('task_done() called too many times')
        self.unfinished_tasks -= 1
        if self.unfinished_tasks == 0:
            self._cond.send(None)

    def join (self):
        """
        Block until all items in the queue have been gotten and processed.

        The count of unfinished tasks goes up whenever an item is added to the queue.
        The count goes down whenever a consumer thread calls :meth:`task_done` to indicate
        that the item was retrieved and all work on it is complete. When the count of
        unfinished tasks drops to zero, :meth:`join` unblocks.
        """
        return self._cond.wait()