view blender/asyncio_thread.py @ 2454:405abed9a45c default tip

fix up asyncio-in-bg-thread sorcery
author drewp@bigasterisk.com
date Mon, 19 May 2025 21:25:32 -0700
parents b23afde50bc2
children
line wrap: on
line source

import asyncio
import sys
from threading import Thread, get_ident
import time
from typing import Coroutine


def log(msg):
    try:
        rl = hex(id(asyncio.get_running_loop()))
    except RuntimeError:
        rl = '(no loop ----)'
    sys.stderr.write(f"thread={hex(get_ident())} loop={rl} {msg}\n")


def startLoopInThread(task: Coroutine) -> asyncio.AbstractEventLoop:
    """
    run a new event loop in a background thread. `task` is run in the new loop.
    Caller should use this (from fg thread) to run further tasks:
      asyncio.run_coroutine_threadsafe(task, returned_loop)

    """
    log('🚋4 startLoopInThread enter ')
    loops = []

    def start_background_loop() -> None:

        async def forever():
            log('🚋6 log_loop')
            loops.append(asyncio.get_running_loop())
            while True:
                await asyncio.sleep(100)

        log('🚋5 make asyncio loop')
        asyncio.run(forever())
        log('🚋19 start_background_loop done')

    t = Thread(target=start_background_loop, daemon=True)
    t.start()
    while not loops:
        time.sleep(.1)
    loop = loops[0]
    log('🚋7 loop has started in thread')

    asyncio.run_coroutine_threadsafe(task, loop)
    log('🚋8 started task')

    log('🚋9 startLoopInThread exit')
    return loop