Launch a thread and wait for its result before exiting the code block.

    >>> with going(lambda: 'return value') as future:
    ...    pass
    >>> future()  # Won't block, the future is ready by now.
    'return value'

    Or discard the result:

    >>> with going(lambda: "don't care"):
    ...    pass


    If an exception is raised within the context, the result is lost:

    >>> with going(lambda: 'return value') as future:
    ...    assert 1 == 0
    Traceback (most recent call last):
    ...
    AssertionError

def going(fn, *args, **kwargs):
    """Launch a thread and wait for its result before exiting the code block.

    >>> with going(lambda: 'return value') as future:
    ...    pass
    >>> future()  # Won't block, the future is ready by now.
    'return value'

    Or discard the result:

    >>> with going(lambda: "don't care"):
    ...    pass


    If an exception is raised within the context, the result is lost:

    >>> with going(lambda: 'return value') as future:
    ...    assert 1 == 0
    Traceback (most recent call last):
    ...
    AssertionError
    """
    future = go(fn, *args, **kwargs)
    try:
        yield future
    except:
        # We are raising an exception, just try to clean up the future.
        exc_info = sys.exc_info()
        try:
            # Shorter than normal timeout.
            future(timeout=1)
        except:
            log_message = ('\nerror in %s:\n'
                           % format_call(inspect.currentframe()))
            sys.stderr.write(log_message)
            traceback.print_exc()
            # sys.stderr.write('exc in %s' % format_call(inspect.currentframe()))
        reraise(*exc_info)
    else:
        # Raise exception or discard result.
        future(timeout=10)