Event loopIn software, an event loop is an algorithm that continually dispatches control flow for events. The loop requests the next event from an event provider (which generally blocks the loop until an event occurs), and when an event is received, invokes its associated event handler. When the event loop is the central event dispatcher of a program, as it often is, it is called the main loop or main event loop. The same algorithm can be used to process inbound messages; a superset of events. In this context, the algorithm is called a message loop, message dispatcher, or message pump. A common use for a message loop is message passing inter-process communication where the message queue is maintained outside of the program (such as by the operating system). Typically, a program that operates in a graphical user interface (GUI) environment uses an event loop, and due to the predominance of GUI environments, most modern applications have a main event loop. In the following pseudocode, loop message := get_next_message() process_message(message) while message != quit AlternativesMany programs include an event loop in the high-level design; a main event loop, but there are alternative designs. A program can exit as soon as it completes the actions that it's designed to do without external (i.e. user) interaction. Often, such a program has optional behavior that is setup before the program starts such as via the command-line interface (CLI) or environment variables. Utility software is often of this nature. Even if a program provides for user interaction, it might not use an event loop. A program that provides an internal CLI does include a command processor that is similar to an event loop in that it dispatches to command handlers based on user input. ExamplesHTML/JavaScriptA web page and its JavaScript typically run in a single-threaded web browser process. The browser process deals with messages from a queue one at a time. A JavaScript function or another browser event might be associated with a given message. When the browser process has finished with a message, it proceeds to the next message in the queue. Windows applicationsIn Windows, a process that interacts with the user must accept and react to incoming messages, which is almost inevitably done by a message loop in that process. In Windows, a message is equated to an event created and imposed upon the operating system. An event can be user interaction, network traffic, system processing, timer activity, inter-process communication, among others. For non-interactive, I/O only events, Windows has I/O completion ports. I/O completion port loops run separately from the Message loop, and do not interact with the Message loop out of the box. The heart of most Win32 applications is the WinMain() function, which calls GetMessage() in a loop. GetMessage() blocks until a message (event), is received (with function PeekMessage() as a non-blocking alternative). After some optional processing, it will call DispatchMessage(), which dispatches the message to the relevant handler, also known as WindowProc. Normally, messages that have no special WindowProc() are dispatched to DefWindowProc, the default one. DispatchMessage() calls the WindowProc of the HWND handle of the message (registered with the RegisterClass() function). More recent versions of Windows guarantee that messages will be delivered to an application's message loop in the order that they were perceived by the system and its peripherals. This guarantee is essential when considering the design consequences of multithreaded applications. However, some messages have different rules, such as messages that are always received last, or messages with a different documented priority.[1] Xlib event loopX applications using Xlib directly are built around the Very few programs use Xlib directly. In the more common case, GUI toolkits based on Xlib usually support adding events. For example, toolkits based on Xt Intrinsics have It is not safe to call Xlib functions from a signal handler, because the X application may have been interrupted in an arbitrary state, e.g. within GLib event loopThe GLib event loop was originally created for use in GTK but is now used in non-GUI applications as well, such as D-Bus. The resource polled is the collection of file descriptors the application is interested in; the polling block will be interrupted if a signal arrives or a timeout expires (e.g. if the application has specified a timeout or idle task). While GLib has built-in support for file descriptor and child termination events, it is possible to add an event source for any event that can be handled in a prepare-check-dispatch model.[2] Application libraries that are built on the GLib event loop include GStreamer and the asynchronous I/O methods of GnomeVFS, but GTK remains the most visible client library. Events from the windowing system (in X, read off the X socket) are translated by GDK into GTK events and emitted as GLib signals on the application's widget objects. macOS Core Foundation run loopsExactly one CFRunLoop is allowed per thread, and arbitrarily many sources and observers can be attached. Sources then communicate with observers through the run loop, with it organising queueing and dispatch of messages. The CFRunLoop is abstracted in Cocoa as an NSRunLoop, which allows any message (equivalent to a function call in non-reflective runtimes) to be queued for dispatch to any object. File-basedIn Unix, the everything is a file paradigm leads to a file-based event loop. Reading from and writing to files, inter-process communication, network communication, and device control are all achieved using file I/O, with the target identified by a file descriptor. The select and poll system calls allow a set of file descriptors to be monitored for a change of state, e.g. when data becomes available to be read. For example, consider a program that reads from a continuously updated file and displays its contents in the X Window System, which communicates with clients over a socket (either Unix domain or Berkeley): def main():
file_fd = open("logfile.log")
x_fd = open_display()
construct_interface()
while True:
rlist, _, _ = select.select([file_fd, x_fd], [], []):
if file_fd in rlist:
data = file_fd.read()
append_to_display(data)
send_repaint_message()
if x_fd in rlist:
process_x_messages()
Signal-basedIn Unix, a signal is an asynchronous event that is handled by a signal handler which runs while the rest of the task is suspended. If a signal is received and handled while the task is blocking in A way to handle a signal is for signal handlers to set a global flag and have the event loop check for the flag immediately before and after the The solution arrived at by POSIX is the An alternative, more portable solution, is to convert asynchronous events to file-based events using the self-pipe trick,[3] where "a signal handler writes a byte to a pipe whose other end is monitored by See alsoReferences
External links |