import concurrent.futures
import time
import asyncio
import threading


def run(coro, loop=None):
    """
    Run coroutine in loop on the current thread. Will block until the coroutine is complete.

    :param coro: the coroutine to run
    :param loop: the event loop to run the coroutine, or a newly created loop if `None`.
    :return: `None`.
    """

    ft = concurrent.futures.Future()

    loop = loop or asyncio.new_event_loop()

    def runner():
        result = loop.run_until_complete(coro)
        ft.set_result(result)
        for task in asyncio.all_tasks(loop=loop):
            task.cancel()
        time.sleep(0.1)

    thread = threading.Thread(target=runner)
    thread.start()
    return ft.result()