def wait(fs, timeout=-1, return_when=ALL_COMPLETED):
    """Wait for the futures in the given sequence to complete.
    Using this function may prevent a worker from executing.

    :param fs: The sequence of Futures to wait upon.
    :param timeout: The maximum number of seconds to wait. If negative or not
        specified, then there is no limit on the wait time.
    :param return_when: Indicates when this function should return. The options
        are:

        ===============   ================================================
        FIRST_COMPLETED   Return when any future finishes or is cancelled.
        FIRST_EXCEPTION   Return when any future finishes by raising an
                          exception. If no future raises an exception then
                          it is equivalent to ALL_COMPLETED.
        ALL_COMPLETED     Return when all futures finish or are cancelled.
        ===============   ================================================

    :return: A named 2-tuple of sets. The first set, named 'done', contains the
        futures that completed (is finished or cancelled) before the wait
        completed. The second set, named 'not_done', contains uncompleted
        futures."""

    DoneAndNotDoneFutures = namedtuple('DoneAndNotDoneFutures', 'done not_done')
    if timeout < 0:
        # Negative timeout means blocking.
        if return_when == FIRST_COMPLETED:
            next(_waitAny(*fs))
        elif return_when in [ALL_COMPLETED, FIRST_EXCEPTION]:
            for _ in _waitAll(*fs):
                pass
        done = set(f for f in fs if f.done())
        not_done = set(fs) - done
        return DoneAndNotDoneFutures(done, not_done)

    elif timeout == 0:
        # Zero-value entry means non-blocking
        control.execQueue.flush()
        control.execQueue.updateQueue()
        done = set(f for f in fs if f._ended())
        not_done = set(fs) - done
        return DoneAndNotDoneFutures(done, not_done)

    else:
        # Any other value means blocking for a given time.
        done = set()
        start_time = time.time()
        while time.time() - start_time < timeout:
            # Flush futures on local queue (to be executed remotely)
            control.execQueue.flush()
            # Block until data arrives (to free CPU time)
            control.execQueue.socket._poll(time.time() - start_time)
            # Update queue
            control.execQueue.updateQueue()

            for f in fs:
                if f._ended():
                    done.add(f)

            not_done = set(fs) - done

            if return_when == FIRST_COMPLETED and len(done) > 0:
                break
            if len(not_done) == 0:
                break
        return DoneAndNotDoneFutures(done, not_done)
Wait for the futures in the given sequence to complete.
    Using this function may prevent a worker from executing.

    :param fs: The sequence of Futures to wait upon.
    :param timeout: The maximum number of seconds to wait. If negative or not
        specified, then there is no limit on the wait time.
    :param return_when: Indicates when this function should return. The options
        are:

        ===============   ================================================
        FIRST_COMPLETED   Return when any future finishes or is cancelled.
        FIRST_EXCEPTION   Return when any future finishes by raising an
                          exception. If no future raises an exception then
                          it is equivalent to ALL_COMPLETED.
        ALL_COMPLETED     Return when all futures finish or are cancelled.
        ===============   ================================================

    :return: A named 2-tuple of sets. The first set, named 'done', contains the
        futures that completed (is finished or cancelled) before the wait
        completed. The second set, named 'not_done', contains uncompleted
        futures.