Ejemplo n.º 1
0
def sync(loop, func, *args, callback_timeout=None, **kwargs):
    """
    Run coroutine in loop running in separate thread.
    """
    callback_timeout = _parse_timedelta(callback_timeout, "s")
    # Tornado's PollIOLoop doesn't raise when using closed, do it ourselves
    if PollIOLoop and (
        (isinstance(loop, PollIOLoop) and getattr(loop, "_closing", False))
        or (hasattr(loop, "asyncio_loop") and loop.asyncio_loop._closed)
    ):
        raise RuntimeError("IOLoop is closed")
    try:
        if loop.asyncio_loop.is_closed():  # tornado 6
            raise RuntimeError("IOLoop is closed")
    except AttributeError:
        pass

    e = threading.Event()
    main_tid = threading.get_ident()
    result = [None]
    error = [False]

    @gen.coroutine
    def f():
        # We flag the thread state asynchronous, which will make sync() call
        # within `func` use async semantic. In order to support concurrent
        # calls to sync(), `asynchronous` is used as a ref counter.
        thread_state.asynchronous = getattr(thread_state, "asynchronous", 0)
        thread_state.asynchronous += 1
        try:
            if main_tid == threading.get_ident():
                raise RuntimeError("sync() called from thread of running loop")
            yield gen.moment
            future = func(*args, **kwargs)
            if callback_timeout is not None:
                future = asyncio.wait_for(future, callback_timeout)
            result[0] = yield future
        except Exception:
            error[0] = sys.exc_info()
        finally:
            assert thread_state.asynchronous > 0
            thread_state.asynchronous -= 1
            e.set()

    loop.add_callback(f)
    if callback_timeout is not None:
        if not e.wait(callback_timeout):
            raise TimeoutError(f"timed out after {callback_timeout} s.")
    else:
        while not e.is_set():
            e.wait(10)
    if error[0]:
        typ, exc, tb = error[0]
        raise exc.with_traceback(tb)
    else:
        return result[0]
Ejemplo n.º 2
0
def sync(loop, func, *args, callback_timeout=None, **kwargs):
    """
    Run coroutine in loop running in separate thread.
    """
    callback_timeout = _parse_timedelta(callback_timeout, "s")
    if loop.asyncio_loop.is_closed():
        raise RuntimeError("IOLoop is closed")

    e = threading.Event()
    main_tid = threading.get_ident()
    result = error = future = None  # set up non-locals

    @gen.coroutine
    def f():
        nonlocal result, error, future
        try:
            if main_tid == threading.get_ident():
                raise RuntimeError("sync() called from thread of running loop")
            yield gen.moment
            future = func(*args, **kwargs)
            if callback_timeout is not None:
                future = asyncio.wait_for(future, callback_timeout)
            future = asyncio.ensure_future(future)
            result = yield future
        except Exception:
            error = sys.exc_info()
        finally:
            e.set()

    def cancel():
        if future is not None:
            future.cancel()

    def wait(timeout):
        try:
            return e.wait(timeout)
        except KeyboardInterrupt:
            loop.add_callback(cancel)
            raise

    loop.add_callback(f)
    if callback_timeout is not None:
        if not wait(callback_timeout):
            raise TimeoutError(f"timed out after {callback_timeout} s.")
    else:
        while not e.is_set():
            wait(10)

    if error:
        typ, exc, tb = error
        raise exc.with_traceback(tb)
    else:
        return result
Ejemplo n.º 3
0
 def sync(self, func, *args, asynchronous=None, callback_timeout=None, **kwargs):
     """Call `func` with `args` synchronously or asynchronously depending on
     the calling context"""
     callback_timeout = _parse_timedelta(callback_timeout)
     if asynchronous is None:
         asynchronous = self.asynchronous
     if asynchronous:
         future = func(*args, **kwargs)
         if callback_timeout is not None:
             future = asyncio.wait_for(future, callback_timeout)
         return future
     else:
         return sync(
             self.loop, func, *args, callback_timeout=callback_timeout, **kwargs
         )
Ejemplo n.º 4
0
def sync(loop, func, *args, callback_timeout=None, **kwargs):
    """
    Run coroutine in loop running in separate thread.
    """
    callback_timeout = _parse_timedelta(callback_timeout, "s")
    if loop.asyncio_loop.is_closed():
        raise RuntimeError("IOLoop is closed")

    e = threading.Event()
    main_tid = threading.get_ident()
    result = [None]
    error = [False]

    @gen.coroutine
    def f():
        try:
            if main_tid == threading.get_ident():
                raise RuntimeError("sync() called from thread of running loop")
            yield gen.moment
            future = func(*args, **kwargs)
            if callback_timeout is not None:
                future = asyncio.wait_for(future, callback_timeout)
            result[0] = yield future
        except Exception:
            error[0] = sys.exc_info()
        finally:
            e.set()

    loop.add_callback(f)
    if callback_timeout is not None:
        if not e.wait(callback_timeout):
            raise TimeoutError(f"timed out after {callback_timeout} s.")
    else:
        while not e.is_set():
            e.wait(10)
    if error[0]:
        typ, exc, tb = error[0]
        raise exc.with_traceback(tb)
    else:
        return result[0]
Ejemplo n.º 5
0
def warn_on_duration(duration, msg):
    start = time()
    yield
    stop = time()
    if stop - start > _parse_timedelta(duration):
        warnings.warn(msg, stacklevel=2)