ipykernel icon indicating copy to clipboard operation
ipykernel copied to clipboard

New event loop integration system

Open davidbrochart opened this issue 10 months ago • 2 comments

I would like to change our event-loop integration with Trio's guest mode. Trio's guest mode also works on asyncio thanks to aioguest. For it to work, we just need to have a function that can schedule a callback in the host event-loop in a thread-safe way.

  • in asyncio, that would be loop.call_soon_threadsafe(callback),
  • in tkinter, that would be tk.after(0, callback).
  • Qt supports Trio's guest mode, see here.
  • ...

For instance, here is how it looks like when the host event-loop is tkinter's:

from tkinter import Tk

from anyio import sleep
from anyioutils import start_guest_run


def run_sync_soon_threadsafe(fn):
    tk.after(0, fn)

def done_callback(outcome):
    print("done")

async def foo():
    for i in range(10):
        await sleep(0.1)
        print(i)

tk = Tk()
start_guest_run(foo, run_sync_soon_threadsafe=run_sync_soon_threadsafe, done_callback=done_callback)
tk.mainloop()

Before calling tk.mainloop(), we call start_guest_run() which runs foo as a task in tkinter's event-loop.

Thoughts?

davidbrochart avatar Feb 27 '25 13:02 davidbrochart

Sounds sensible to me, assuming everything works as advertized

minrk avatar Feb 28 '25 14:02 minrk

I did some experiments with Qt, it works fine on asyncio and Trio. And the nice thing is that there is no polling involved, as in our current solution. For asyncio one could argue that aioguest uses greenlet, which manipulates the C stack, but on the other hand SQLAlchemy's whole async architecture is based on greenlet. PyPy also supports greenlet.

davidbrochart avatar Feb 28 '25 14:02 davidbrochart