Pregunta

When you create programs (like a socket server) that are designed to run on an operating system, such as Ubuntu, frameworks like Qt for C++ use something called a main event loop:

app = new QCoreApplication(argc, argv);
int rc = app->exec()

Now programming language like C or C++ enable a program to make system calls through built-in functions, like fork() or pthread_create() and use software interrupts to change kernel mode. For example, the program can request use of the kernel by means of a system call in order to perform privileged instructions, such as process creation or input/output operations. Other examples are open, read, write, close, wait, execve, fork, exit, and kill. All this can be achieved within C/C++ directly without an event loop.

So what's the purpose of the event loop?

¿Fue útil?

Solución

Comparing event loop to system calls, is similar to comparing apples to.... cars and not just orange cars.

System calls are used as part of your normal, structured control flow. You do X, Y, system call then Z. As you pointed out, the purpose of system calls is to give your app to subsystems which are managed by the kernel. Since those subsystems are shared/accessed by multiple processes, you must cross the boundary from user into kernel space in order to work with them.

Event loops, on the other hand live completely in your user space. They are the basis of an Event Driven Programming (EDP), which is very common GUI applications but also has uses in many other areas. Instead of having one control structure that does "X, Y, sleep, Z, system call..." in EDP you define small snippets of code (i.e. event handlers) and their job is to respond to particular events. Event loop is what dispatches those events to their respective handlers, at the most basic level, it is nothing more than a queue and a lookup table with function pointers.

Since GUI applications are by their nature event driven (i.e. user clicks here and there), event loops are just about universally used to drive them. One reason for using events in a GUI is let's say you want something to blink every 2 seconds. If you had a non-GUI app, you could implement a simple loop with sleep(2), but if you call sleep() in a GUI, your application would freeze since the loop would no longer respond to mouse/keyboard clicks from the user. The way around it, would be to create a timer that fires an event every 2 seconds. This way the loop will continue to dispatch all other events and every 2 minutes your timer handler would be invoked to change the color of whatever it is you are blinking.


To clarify what an event loop is (in pseudo code):

   while(true) {
      event = GetEvent()  // will sleep until next event arrives
      DispatchEvent(event)
   }

This can run on just about any thread, but would typically be on the main one that started the app. Inside DispatchEvent, you simply have a lookup map, that maps event types (e.g. an int) to one or more event handlers (function pointer, interfaces pointers... etc) registered to listen for that event.

Otros consejos

At the system level its all the same. You waggle a mouse, press a key, stroke the screen, receive a wireless packet, this triggers a system level interrupt, which executes the chunk of code assigned to the interrupt.

However at a higher level there are two distinct programming styles commonly used.

The "callback" --> you assign a chunk of your code to be run when an event occurs. As several events may overlap you need your program to be multi-threaded and your event handlers to be thread-safe. The advantage is a more responsive program, the disadvantage is the extra effort to ensure thread safety and the impossibility of testing all possible combinations of events.

The "event loop" --> the chunk of code assigned to an event merely records the event in a table/stack/list. The main thread of your program then scans the list for events and runs the necessary code to process the event. The disadvantage is a less responsive program as you need to completely finish processing one event before going on to the next, the advantages are simpler code as all events are processed by a single thread, and, the possibility of complete test coverage.

You started with mentioning Qt, it's a good starting point. Qt is a GUI library. A GUI usually works with kinds of external events which could be predicted, because originate in user's activity. Graphic environments like Windows (Microsoft), X Window, Mac, all current smartphone/tablet environments, etc. allow user to make essentially any input he could "send", as pressing keys (not only on keyboard), mouse events, touchscreen gestures, etc.

If a program is written sequentially, processing all such events becames, saying colloquially, an unbearable level of both headache and butthurt at the same time. Instead of, organizing a program as event driven solves this. There are event generators, dispatcher and event processors. If a mouse key is pressed, the corresponding event is sent to a widget currently pointed. No complex code is needed in that case to provide matching against the current visible widget and window set; OTOH, if this code had written, it would be practically identical to the dispatching code in event loop based engine.

Similarly, if I write an application which supports 100k clients over network connections, I won't iterate all them to check whether new data has arrived. I will add their listenings to event engine and simply wait any incoming events in callbacks. It's not something artificial - it's the consequence of natural evolution of dealing with multiple event sources, provided "event" here is an abstract definition of something that program shall react to.

So, event loops and, in general, event-based programming isn't a thing which contradicts to all techniques you have mentioned; no, it's just a level upper than they are. Event handlers can then use file I/O, socket I/O, etc.

Licenciado bajo: CC-BY-SA con atribución
scroll top