import asyncio

# Optional event loop for use throughout the program
CUR_LOOP = None

def start_loop() -> asyncio.BaseEventLoop:
    "Start an event loop for all future coroutines to run in. Necessary if executing multiple reasoning runs."
    global CUR_LOOP
    CUR_LOOP = asyncio.get_event_loop()
    print(f"New event loop: {CUR_LOOP}")
    
    return CUR_LOOP

def run_coroutine(coroutine):
    "Run an async function from a sync environment, without starting multiple event loops."
    global CUR_LOOP
    
    try:
        # If start_loop is called before, use the loop created then
        if CUR_LOOP is not None:
            loop = CUR_LOOP
        else:
            loop = asyncio.get_running_loop()

    except RuntimeError:
        # No loop is running, so we can safely use asyncio.run()
        return asyncio.run(coroutine)
    
    # Schedule the coroutine and get the result
    return loop.run_until_complete(coroutine)