Event loop

Event loop

In computer science, the event loop, message dispatcher, message loop, message pump, or run loop is a programming construct that waits for and dispatches events or messages in a program. It works by polling some internal or external "event provider", which generally blocks until an event has arrived, and then calls the relevant event handler ("dispatches the event"). The event-loop may be used in conjunction with a reactor, if the event provider follows the file interface (which can be selected or polled). The event loop almost always operates asynchronously with the message originator.

When the event loop forms the central control flow construct of a program, as it often does, and is thus at the highest level of control within the program, it may be termed the main loop or main event loop.

Contents

Message passing

Message pumps are said to 'pump' messages from the program's message queue (assigned and usually owned by the underlying operating system) into the program for processing. In the strictest sense, an event loop is one of the methods for implementing inter-process communication. In fact, message processing exists in many systems, including a kernel-level component of the Mach operating system. The event loop is a specific implementation technique of systems that use message passing.

Alternative designs

This approach is in contrast to a number of other alternatives:

  • Traditionally, a program simply ran once then terminated. This type of program was very common in the early days of computing, and lacked any form of user interactivity. This is still used frequently, particularly in the form of command line driven programs. Any parameters are set up in advance and passed in one go when the program starts.
  • Menu-driven designs. These still may feature a main loop but are not usually thought of as event driven in the usual sense. Instead, the user is presented with an ever-narrowing set of options until the task they wish to carry out is the only option available. Limited interactivity through the menus is available.

Usage

Due to the predominance of GUI interfaces, most modern applications feature a main loop. The get_next_message() routine is typically provided by the operating system, and blocks until a message is available. Thus, the loop is only entered when there is something to process.

function main
    initialize()
    while message != quit
        message := get_next_message()
        process_message(message)
    end while
end function

File interface

Under Unix, the "everything is a file" paradigm naturally 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):

main():     
    file_fd = open ("logfile")
    x_fd = open_display ()
    construct_interface ()
    while changed_fds = select ({file_fd, x_fd}):
        if file_fd in changed_fds:
            data = read_from (file_fd)
            append_to_display (data)
            send_repaint_message ()
        if x_fd in changed_fds:
            process_x_messages ()

Handling signals

One of the few things in Unix that do not conform to the file interface are asynchronous events (signals). Signals are received in signal handlers, small, limited pieces of code that run while the rest of the task is suspended; if a signal is received and handled while the task is blocking in select() then select will return early with EINTR; if a signal is received while the task is CPU bound then the task will be suspended between instructions until the signal handler returns.

Thus an obvious way to handle signals is for signal handlers to set a global flag and have the event loop check for the flag immediately before and after the select() call; if it is set, handle the signal in the same manner as with events on file descriptors. Unfortunately, this gives rise to a race condition: if a signal arrives immediately between checking the flag and calling select(), then it will not be handled until select() returns for some other reason (for example, being interrupted by a frustrated user).

The solution arrived at by POSIX is the pselect call, which is similar to select() but takes an additional sigmask parameter, which describes a signal mask. This allows an application to mask signals in the main task, then remove the mask for the duration of the select() call, such that signal handlers are only called while the application is I/O bound. However, implementations of pselect() have only recently become reliable; versions of Linux prior to 2.6.16 do not have a pselect() system call, forcing glibc to emulate it via a method prone to the very same race condition pselect() is intended to avoid.

An alternative, more portable solution, is to convert asynchronous events to file-based events using the self-pipe trick[1], where "a signal handler writes a byte to a pipe whose other end is monitored by select() in the main program".[2] In Linux kernel version 2.6.22, a new system call signalfd() was added, which allows receiving signals via a special file descriptor.

Implementations

Windows applications

The Microsoft Windows operating system requires user-interactive processes that wish to run on the operating system to construct a message loop for responding to events. In this operating system, a message is equated to an event created and imposed upon the operating system. An event can range from user interaction, network traffic, system processing, timer activity, and interprocess communication among others. For non-interactive, I/O only events, Windows has IO Completion Ports. IO 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, or "event", is received. 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 window-proc of the HWND handle of the message (Registered with the RegisterClass function).

Message ordering

More recent versions of Microsoft Windows provide the guarantee to the programmer 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.[3]

X Window System

Xlib event loop

X applications using Xlib directly are built around the XNextEvent family of functions; XNextEvent blocks until an event appears on the event queue, whereupon the application processes it appropriately. The Xlib event loop only handles window system events; applications which need to be able to wait on other files and devices could construct their own event loop from primitives such as ConnectionNumber, but in practice tend to use multithreading.

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 XtAppAddInput() and XtAppAddTimeout().

Please note that 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 XNextEvent. See [1] for a solution for X11R5, X11R6 and Xt.

GLib event loop

The 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.

Core Foundation run loops

Exactly 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.

See also

References

  1. ^ D. J. Bernstein. "The self-pipe trick". http://cr.yp.to/docs/selfpipe.html. 
  2. ^ BUGS, pselect(2): synchronous I/O multiplexing – Linux System Calls Manual
  3. ^ GetMessage() function with message priority list.

External links


Wikimedia Foundation. 2010.

Игры ⚽ Нужно решить контрольную?

Look at other dictionaries:

  • Loop-switch sequence — A loop switch sequence is a specific derivative of the spaghetti code programming antipattern where a clear set of steps is implemented as a byzantine switch within a loop. Also known as The FOR CASE paradigm… …   Wikipedia

  • Event-Recorder — Herzfrequenz Diagramm eines LZ EKG, das zwischen 23:00 Uhr und 03:20 Uhr (Zeitachse unten) eine Episode von Vorhofflimmern erkennen lässt Als Langzeit EKG (Abk. LZ EKG) wird in der Medizin die Registrierung des Elektrokardiogramms über einen… …   Deutsch Wikipedia

  • Event generator — Event generators are software libraries that generate simulated high energy particle physics events [ [http://arjournals.annualreviews.org/doi/abs/10.1146/annurev.nucl.55.090704.151505 M. L. Mangano T. J. Stelzer, Ann. Rev. Nucl. Part. Sci. 55,… …   Wikipedia

  • Event-driven programming — Programming paradigms Agent oriented Automata based Component based Flow based Pipelined Concatenative Concurrent computin …   Wikipedia

  • Loop quantum gravity — Not to be confused with the path integral formulation of LQG, see spin foam. This article is about LQG in its Canonical formulation.. Beyond the Standard Model …   Wikipedia

  • Message loop in Microsoft Windows — Microsoft Windows programs are event based. They act upon messages that the operating system posts to the main thread of the application. These messages are received from the message queue by the application by repeatedly calling the GetMessage… …   Wikipedia

  • Discrete event simulation — In discrete event simulation, the operation of a system is represented as a chronological sequence of events. Each event occurs at an instant in time and marks a change of state in the system [1]. For example, if an elevator is simulated, an… …   Wikipedia

  • Causality loop — *A temporal causality loop, or predestination paradox, is a theoretical phenomenon, which is said to occur when a chain of cause effect events is circular. For instance, if event A causes event B, and event B causes event C, and event C causes… …   Wikipedia

  • Time loop — A time loop or temporal loop is a common plot device in science fiction (especially in universes where time travel is commonplace) in which time runs normally for a set period (usually a day or a few hours) but then skips back like a broken… …   Wikipedia

  • Tape loop — Tape loops are loops of prerecorded magnetic tape used to create repetitive, rhythmic musical patterns or dense layers of sound. Contemporary composers such as Steve Reich and Karlheinz Stockhausen used tape loops to create phase patterns and… …   Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”