Example #1
0
 def __init__(self, maxsize=0):
     self.maxsize = maxsize
     self._init(maxsize)
     # mutex must be held whenever the queue is mutating.  All methods
     # that acquire mutex must release it before returning.  mutex
     # is shared between the three conditions, so acquiring and
     # releasing the conditions also acquires and releases mutex.
     self.mutex = Lock()
     # Notify not_empty whenever an item is added to the queue; a
     # task waiting to get is notified then.
     self.not_empty = Condition(self.mutex)
     # Notify not_full whenever an item is removed from the queue;
     # a task waiting to put is notified then.
     self.not_full = Condition(self.mutex)
     # Notify all_tasks_done whenever the number of unfinished tasks
     # drops to zero; task waiting to join() is notified to resume
     self.all_tasks_done = Condition(self.mutex)
     self.unfinished_tasks = 0
Example #2
0
 def __init__(self, maxsize=0):
     self.maxsize = maxsize
     self._init(maxsize)
     # mutex must be held whenever the queue is mutating.  All methods
     # that acquire mutex must release it before returning.  mutex
     # is shared between the three conditions, so acquiring and
     # releasing the conditions also acquires and releases mutex.
     self.mutex = Lock()
     # Notify not_empty whenever an item is added to the queue; a
     # task waiting to get is notified then.
     self.not_empty = Condition(self.mutex)
     # Notify not_full whenever an item is removed from the queue;
     # a task waiting to put is notified then.
     self.not_full = Condition(self.mutex)
     # Notify all_tasks_done whenever the number of unfinished tasks
     # drops to zero; task waiting to join() is notified to resume
     self.all_tasks_done = Condition(self.mutex)
     self.unfinished_tasks = 0
Example #3
0
 def __init__(self):
     self._lock = Lock()
     self._cond = Condition(Lock())
     self._locked = False
     self._used = False
     self._exc = self._value = Null
Example #4
0
class Result(object):
    """
    Result is an internal object which is meant to be used like a Future, but being more
    lightweight and supporting a single waiter. Example:

    result = Result()

    def f1():
        with result:
            some_async_func()
            return result.get()

    def some_async_func():
        # this function runs in a different task
        ...
        result.set_value(42)
    """

    __slots__ = ['_lock', '_cond', '_locked', '_used', '_exc', '_value']

    def __init__(self):
        self._lock = Lock()
        self._cond = Condition(Lock())
        self._locked = False
        self._used = False
        self._exc = self._value = Null

    def acquire(self):
        self._lock.acquire()
        self._locked = True

    def release(self):
        self._lock.release()
        self._locked = False
        self._used = False
        self._exc = self._value = Null

    def get(self):
        assert self._locked
        assert not self._used
        try:
            with self._cond:
                if self._exc == self._value == Null:
                    self._cond.wait()
            if self._exc != Null:
                raise self._exc
            assert self._value != Null
            return self._value
        finally:
            self._used = True
            self._exc = self._value = Null

    def set_value(self, value):
        assert self._locked
        assert not self._used
        assert self._exc == self._value == Null
        with self._cond:
            self._value = value
            self._cond.notify_all()

    def set_exception(self, value):
        assert self._locked
        assert not self._used
        assert self._exc == self._value == Null
        with self._cond:
            self._exc = value
            self._cond.notify_all()

    def __enter__(self):
        self.acquire()

    def __exit__(self, typ, val, tb):
        self.release()
Example #5
0
 def __init__(self):
     self._cond = Condition(Lock())
     self._flag = False
Example #6
0
class Queue(object):
    """Create a queue object with a given maximum size.

    If maxsize is <= 0, the queue size is infinite.
    """
    def __init__(self, maxsize=0):
        self.maxsize = maxsize
        self._init(maxsize)
        # mutex must be held whenever the queue is mutating.  All methods
        # that acquire mutex must release it before returning.  mutex
        # is shared between the three conditions, so acquiring and
        # releasing the conditions also acquires and releases mutex.
        self.mutex = Lock()
        # Notify not_empty whenever an item is added to the queue; a
        # task waiting to get is notified then.
        self.not_empty = Condition(self.mutex)
        # Notify not_full whenever an item is removed from the queue;
        # a task waiting to put is notified then.
        self.not_full = Condition(self.mutex)
        # Notify all_tasks_done whenever the number of unfinished tasks
        # drops to zero; task waiting to join() is notified to resume
        self.all_tasks_done = Condition(self.mutex)
        self.unfinished_tasks = 0

    def task_done(self):
        """Indicate that a formerly enqueued task is complete.

        Used by Queue consumer tasks.  For each get() used to fetch a task,
        a subsequent call to task_done() tells the queue that the processing
        on the task is complete.

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

        Raises a ValueError if called more times than there were items
        placed in the queue.
        """
        self.all_tasks_done.acquire()
        try:
            unfinished = self.unfinished_tasks - 1
            if unfinished <= 0:
                if unfinished < 0:
                    raise ValueError('task_done() called too many times')
                self.all_tasks_done.notify_all()
            self.unfinished_tasks = unfinished
        finally:
            self.all_tasks_done.release()

    def join(self):
        """Blocks 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 task calls task_done()
        to indicate the item was retrieved and all work on it is complete.

        When the count of unfinished tasks drops to zero, join() unblocks.
        """
        self.all_tasks_done.acquire()
        try:
            while self.unfinished_tasks:
                self.all_tasks_done.wait()
        finally:
            self.all_tasks_done.release()

    def qsize(self):
        """Return the approximate size of the queue (not reliable!)."""
        self.mutex.acquire()
        n = self._qsize()
        self.mutex.release()
        return n

    def empty(self):
        """Return True if the queue is empty, False otherwise (not reliable!).

        This method is likely to be removed at some point.  Use qsize() == 0
        as a direct substitute, but be aware that either approach risks a race
        condition where a queue can grow before the result of empty() or
        qsize() can be used.

        To create code that needs to wait for all queued tasks to be
        completed, the preferred technique is to use the join() method.

        """
        self.mutex.acquire()
        n = not self._qsize()
        self.mutex.release()
        return n

    def full(self):
        """Return True if the queue is full, False otherwise (not reliable!).

        This method is likely to be removed at some point.  Use qsize() >= n
        as a direct substitute, but be aware that either approach risks a race
        condition where a queue can shrink before the result of full() or
        qsize() can be used.

        """
        self.mutex.acquire()
        n = 0 < self.maxsize <= self._qsize()
        self.mutex.release()
        return n

    def put(self, item, block=True, timeout=None):
        """Put an item into the queue.

        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until a free slot is available. If 'timeout' is
        a positive number, it blocks at most 'timeout' seconds and raises
        the Full exception if no free slot was available within that time.
        Otherwise ('block' is false), put an item on the queue if a free slot
        is immediately available, else raise the Full exception ('timeout'
        is ignored in that case).
        """
        self.not_full.acquire()
        try:
            if self.maxsize > 0:
                if not block:
                    if self._qsize() >= self.maxsize:
                        raise Full
                elif timeout is None:
                    while self._qsize() >= self.maxsize:
                        self.not_full.wait()
                elif timeout < 0:
                    raise ValueError("'timeout' must be a positive number")
                else:
                    if self._qsize() >= self.maxsize:
                        self.not_full.wait(timeout)
                        if self._qsize() >= self.maxsize:
                            raise Full
            self._put(item)
            self.unfinished_tasks += 1
            self.not_empty.notify()
        finally:
            self.not_full.release()

    def put_nowait(self, item):
        """Put an item into the queue without blocking.

        Only enqueue the item if a free slot is immediately available.
        Otherwise raise the Full exception.
        """
        return self.put(item, False)

    def get(self, block=True, timeout=None):
        """Remove and return an item from the queue.

        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until an item is available. If 'timeout' is
        a positive number, it blocks at most 'timeout' seconds and raises
        the Empty exception if no item was available within that time.
        Otherwise ('block' is false), return an item if one is immediately
        available, else raise the Empty exception ('timeout' is ignored
        in that case).
        """
        self.not_empty.acquire()
        try:
            if not block:
                if not self._qsize():
                    raise Empty
            elif timeout is None:
                while not self._qsize():
                    self.not_empty.wait()
            elif timeout < 0:
                raise ValueError("'timeout' must be a positive number")
            else:
                if not self._qsize():
                    self.not_empty.wait(timeout)
                    if not self._qsize():
                        raise Empty
            item = self._get()
            self.not_full.notify()
            return item
        finally:
            self.not_empty.release()

    def get_nowait(self):
        """Remove and return an item from the queue without blocking.

        Only get an item if one is immediately available. Otherwise
        raise the Empty exception.
        """
        return self.get(False)

    # Override these methods to implement other queue organizations
    # (e.g. stack or priority queue).
    # These will only be called with appropriate locks held

    # Initialize the queue representation
    def _init(self, maxsize):
        self.queue = deque()

    def _qsize(self):
        return len(self.queue)

    # Put a new item in the queue
    def _put(self, item):
        self.queue.append(item)

    # Get an item from the queue
    def _get(self):
        return self.queue.popleft()
Example #7
0
 def __init__(self):
     self._send_lock = Lock()
     self._recv_lock = Lock()
     self._new_data = Event()
     self._recv_data = Event()
     self._data = None
Example #8
0
 def __init__(self, max_workers):
     self._max_workers = max_workers
     self._tasks = set()
     self._work_queue = Queue()
     self._shutdown = False
     self._shutdown_lock = Lock()
Example #9
0
 def __init__(self):
     super(_AsCompletedWaiter, self).__init__()
     self.lock = Lock()
Example #10
0
 def __init__(self, num_pending_calls, stop_on_exception):
     self.num_pending_calls = num_pending_calls
     self.stop_on_exception = stop_on_exception
     self.lock = Lock()
     super(_AllCompletedWaiter, self).__init__()
Example #11
0
class Queue(object):
    """Create a queue object with a given maximum size.

    If maxsize is <= 0, the queue size is infinite.
    """
    def __init__(self, maxsize=0):
        self.maxsize = maxsize
        self._init(maxsize)
        # mutex must be held whenever the queue is mutating.  All methods
        # that acquire mutex must release it before returning.  mutex
        # is shared between the three conditions, so acquiring and
        # releasing the conditions also acquires and releases mutex.
        self.mutex = Lock()
        # Notify not_empty whenever an item is added to the queue; a
        # task waiting to get is notified then.
        self.not_empty = Condition(self.mutex)
        # Notify not_full whenever an item is removed from the queue;
        # a task waiting to put is notified then.
        self.not_full = Condition(self.mutex)
        # Notify all_tasks_done whenever the number of unfinished tasks
        # drops to zero; task waiting to join() is notified to resume
        self.all_tasks_done = Condition(self.mutex)
        self.unfinished_tasks = 0

    def task_done(self):
        """Indicate that a formerly enqueued task is complete.

        Used by Queue consumer tasks.  For each get() used to fetch a task,
        a subsequent call to task_done() tells the queue that the processing
        on the task is complete.

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

        Raises a ValueError if called more times than there were items
        placed in the queue.
        """
        self.all_tasks_done.acquire()
        try:
            unfinished = self.unfinished_tasks - 1
            if unfinished <= 0:
                if unfinished < 0:
                    raise ValueError('task_done() called too many times')
                self.all_tasks_done.notify_all()
            self.unfinished_tasks = unfinished
        finally:
            self.all_tasks_done.release()

    def join(self):
        """Blocks 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 task calls task_done()
        to indicate the item was retrieved and all work on it is complete.

        When the count of unfinished tasks drops to zero, join() unblocks.
        """
        self.all_tasks_done.acquire()
        try:
            while self.unfinished_tasks:
                self.all_tasks_done.wait()
        finally:
            self.all_tasks_done.release()

    def qsize(self):
        """Return the approximate size of the queue (not reliable!)."""
        self.mutex.acquire()
        n = self._qsize()
        self.mutex.release()
        return n

    def empty(self):
        """Return True if the queue is empty, False otherwise (not reliable!).

        This method is likely to be removed at some point.  Use qsize() == 0
        as a direct substitute, but be aware that either approach risks a race
        condition where a queue can grow before the result of empty() or
        qsize() can be used.

        To create code that needs to wait for all queued tasks to be
        completed, the preferred technique is to use the join() method.

        """
        self.mutex.acquire()
        n = not self._qsize()
        self.mutex.release()
        return n

    def full(self):
        """Return True if the queue is full, False otherwise (not reliable!).

        This method is likely to be removed at some point.  Use qsize() >= n
        as a direct substitute, but be aware that either approach risks a race
        condition where a queue can shrink before the result of full() or
        qsize() can be used.

        """
        self.mutex.acquire()
        n = 0 < self.maxsize <= self._qsize()
        self.mutex.release()
        return n

    def put(self, item, block=True, timeout=None):
        """Put an item into the queue.

        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until a free slot is available. If 'timeout' is
        a positive number, it blocks at most 'timeout' seconds and raises
        the Full exception if no free slot was available within that time.
        Otherwise ('block' is false), put an item on the queue if a free slot
        is immediately available, else raise the Full exception ('timeout'
        is ignored in that case).
        """
        self.not_full.acquire()
        try:
            if self.maxsize > 0:
                if not block:
                    if self._qsize() >= self.maxsize:
                        raise Full
                elif timeout is None:
                    while self._qsize() >= self.maxsize:
                        self.not_full.wait()
                elif timeout < 0:
                    raise ValueError("'timeout' must be a positive number")
                else:
                    endtime = _time() + timeout
                    while self._qsize() >= self.maxsize:
                        remaining = endtime - _time()
                        if remaining <= 0.0:
                            raise Full
                        self.not_full.wait(remaining)
            self._put(item)
            self.unfinished_tasks += 1
            self.not_empty.notify()
        finally:
            self.not_full.release()

    def put_nowait(self, item):
        """Put an item into the queue without blocking.

        Only enqueue the item if a free slot is immediately available.
        Otherwise raise the Full exception.
        """
        return self.put(item, False)

    def get(self, block=True, timeout=None):
        """Remove and return an item from the queue.

        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until an item is available. If 'timeout' is
        a positive number, it blocks at most 'timeout' seconds and raises
        the Empty exception if no item was available within that time.
        Otherwise ('block' is false), return an item if one is immediately
        available, else raise the Empty exception ('timeout' is ignored
        in that case).
        """
        self.not_empty.acquire()
        try:
            if not block:
                if not self._qsize():
                    raise Empty
            elif timeout is None:
                while not self._qsize():
                    self.not_empty.wait()
            elif timeout < 0:
                raise ValueError("'timeout' must be a positive number")
            else:
                endtime = _time() + timeout
                while not self._qsize():
                    remaining = endtime - _time()
                    if remaining <= 0.0:
                        raise Empty
                    self.not_empty.wait(remaining)
            item = self._get()
            self.not_full.notify()
            return item
        finally:
            self.not_empty.release()

    def get_nowait(self):
        """Remove and return an item from the queue without blocking.

        Only get an item if one is immediately available. Otherwise
        raise the Empty exception.
        """
        return self.get(False)

    # Override these methods to implement other queue organizations
    # (e.g. stack or priority queue).
    # These will only be called with appropriate locks held

    # Initialize the queue representation
    def _init(self, maxsize):
        self.queue = deque()

    def _qsize(self):
        return len(self.queue)

    # Put a new item in the queue
    def _put(self, item):
        self.queue.append(item)

    # Get an item from the queue
    def _get(self):
        return self.queue.popleft()
Example #12
0
 def __init__(self):
     self._lock = Lock()
     self._cond = Condition(Lock())
     self._locked = False
     self._used = False
     self._exc = self._value = Null
Example #13
0
class Result(object):
    """
    Result is an internal object which is meant to be used like a Future, but being more
    lightweight and supporting a single waiter. Example:

    result = Result()

    def f1():
        with result:
            some_async_func()
            return result.get()

    def some_async_func():
        # this function runs in a different task
        ...
        result.set_value(42)
    """

    __slots__ = ['_lock', '_cond', '_locked', '_used', '_exc', '_value']

    def __init__(self):
        self._lock = Lock()
        self._cond = Condition(Lock())
        self._locked = False
        self._used = False
        self._exc = self._value = Null

    def acquire(self):
        self._lock.acquire()
        self._locked = True

    def release(self):
        self._lock.release()
        self._locked = False
        self._used = False
        self._exc = self._value = Null

    def get(self):
        assert self._locked
        assert not self._used
        try:
            with self._cond:
                if self._exc == self._value == Null:
                    self._cond.wait()
            if self._exc != Null:
                raise self._exc
            assert self._value != Null
            return self._value
        finally:
            self._used = True
            self._exc = self._value = Null

    def set_value(self, value):
        assert self._locked
        assert not self._used
        assert self._exc == self._value == Null
        with self._cond:
            self._value = value
            self._cond.notify_all()

    def set_exception(self, value):
        assert self._locked
        assert not self._used
        assert self._exc == self._value == Null
        with self._cond:
            self._exc = value
            self._cond.notify_all()

    def __enter__(self):
        self.acquire()

    def __exit__(self, typ, val, tb):
        self.release()