dls-controls / pythonSoftIOC

Embed an EPICS IOC in a Python process
Apache License 2.0
32 stars 7 forks source link

Passing a custom asyncio event loop into the AsyncioDispatcher causes methods to never run #95

Closed AlexanderWells-diamond closed 1 year ago

AlexanderWells-diamond commented 1 year ago

Passing a custom loop to the AsyncioDispatcher causes no on_update methods to be called. This can be seen in this code by running it and running caput ABC:AO 1, and observing the lack of output. Uncomment the second event_loop definition to see it working.

# Import the basic framework components.
from softioc import softioc, builder, asyncio_dispatcher
import asyncio

# Create an asyncio dispatcher, the event loop is now running
event_loop = asyncio.get_event_loop()
# event_loop = None
dispatcher = asyncio_dispatcher.AsyncioDispatcher(event_loop)

# Set the record prefix
builder.SetDeviceName("ABC")

# Create some records
ao = builder.aOut('AO', initial_value=12.45, always_update=True,
                  on_update=print)

# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit(dispatcher)

# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())

This is caused by the event loop that is retrieved by asyncio.get_event_loop() not running anywhere.

If there's no event loop, we create our own and set it running forever in its own newly created thread. We need to implement something similar to this for passed in event loops - possibly use loop.is_running() to know if its already running somewhere else, and if not we create a new thread for it to run in.

We should also take this time to document the AsyncioDispatcher, which currently has no explicit documentation - there's one line about the module it's in but nothing about the class itself, nor any limitations on what loop we can pass in.

(An alternative solution to this is to simply remove the ability to pass in custom event loops. However, as we have released versions with this API that's probably not desirable)