Unsynchronize asyncio by using an ambient event loop in a separate thread.
* Mark all async functions with @unsync. May also mark regular functions to execute in a separate thread.
* All @unsync functions, async or not, return an Unfuture
* All Futures must be Unfutures which includes the result of an @unsync function call, or wrapping Unfuture(asyncio.Future) or Unfuture(concurrent.Future). Unfuture combines the behavior of asyncio.Future and concurrent.Future:
* Unfuture.set_value is threadsafe unlike asyncio.Future
* Unfuture instances can be awaited, even if made from concurrent.Future
* Unfuture.result() is a blocking operation except in unsync.loop/unsync.thread where it behaves like asyncio.Future.result and will throw an exception if the future is not done
* Functions will execute in different contexts:
* @unsync async functions will execute in an event loop in unsync.thread
* @unsync regular functions will execute in unsync.thread_executor, a ThreadPoolExecutor
* @unsync(cpu_bound=True) regular functions will execute in unsync.process_executor, a ProcessPoolExecutor