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?