-
-
Notifications
You must be signed in to change notification settings - Fork 718
Description
This is part of a larger effort to rework the main loop (#1778)
The action handler in a module runs in the caller thread (the controller thread) and not in the module thread. This requires us to be very careful about concurrent access and synchronization. Some modules solve this by creating a new connection to their adapter whenever an action is called (i3, mpd). For most other modules it is not clear whether the action code is actually save, it just seems to work (in almost all cases the action code will be called while the module sleeps).
I think we should do three things:
- Create an event queue inside each module. When the controller wants to deliver an action, it can put that action into the event queue and wake the module (if it is sleeping). After waking up the module works through all received actions (in the module thread). We can either use the lock-free queue we are already using in the controller or just have a lock on the queue.
- Clearly define the interface of a module and which functions may be called from other threads and which must be called from the module thread.
- Ensure that all modules adhere to that interface and don't cause concurrency issues.
The general idea is to put as much as possible into the module threads and let the controller communicate with the module through only a narrow interface. If possible, using only atomic primitive variables or small locks around certain variables (e.g. the module output).