Let’s say I have a program which consists of a main event loop. The event loop should check for tasks and if one exists, it is to be processed. The user interface consists of a GUI with buttons, for each of which can be defined a callback function when it is pressed.
Using multiple threads, I can simply execute the event loop in a separate thread. When a button is pressed, I feed a task into a queue which is shared by the UI and the event thread. The event thread then consumes and executes the task.
My question is how this behaviour is realized in a single threaded application or a language that does not support multithreading. My idea is to poll for user interaction, but how does this work in said GUI where a button press can only be registered by the invocation of a specified callback?
The OS creates events and feeds it into the OS-supplied Event queue which the application polls in the event loop.
In Windows that is with GetMessage
and friends.
Windowing frameworks (java’s swing, Qt etc.) will implement this loop for you and allow you to insert your own custom events.
You can mix several tasks in a single threaded loop, e.g. by using idle functions (as I explained here).
So with a GUI event loop, when some external event happens (e.g. the user presses a button), the callback could add an idle function into the loop.
Then it is important that the idle function gives back the control to the event loop quite quickly (typically, in a few milliseconds). It could add itself again to the loop to continue some processing.
Of course, the concept of continuations is relevant, and you can see an idle-function re-adding itself as some hand-written continuation-passing style
See also this answer for more references.