Next: , Previous: IO Channels, Up: Top


5 The Main Event Loop

manages all available sources of events.

5.1 Overview

The main event loop manages all the available sources of events for GLib and GTK+ applications. These events can come from any number of different types of sources such as file descriptors (plain files, pipes or sockets) and timeouts. New types of event sources can also be added using g-source-attach.

To allow multiple independent sets of sources to be handled in different threads, each source is associated with a <g-main-context>. A <g-main-context> can only be running in a single thread, but sources can be added to it and removed from it from other threads.

Each event source is assigned a priority. The default priority, <g-priority-default>, is 0. Values less than 0 denote higher priorities. Values greater than 0 denote lower priorities. Events from high priority sources are always processed before events from lower priority sources.

Idle functions can also be added, and assigned a priority. These will be run whenever no events with a higher priority are ready to be processed.

The <g-main-loop> data type represents a main event loop. A <g-main-loop> is created with g-main-loop-new. After adding the initial event sources, g-main-loop-run is called. This continuously checks for new events from each of the event sources and dispatches them. Finally, the processing of an event from one of the sources leads to a call to g-main-loop-quit to exit the main loop, and g-main-loop-run returns.

It is possible to create new instances of <g-main-loop> recursively. This is often used in GTK+ applications when showing modal dialog boxes. Note that event sources are associated with a particular <g-main-context>, and will be checked and dispatched for all main loops associated with that <g-main-context>.

GTK+ contains wrappers of some of these functions, e.g. gtk-main, gtk-main-quit and gtk-events-pending.

5.2 Creating new sources types

One of the unusual features of the GTK+ main loop functionality is that new types of event source can be created and used in addition to the builtin type of event source. A new event source type is used for handling GDK events. A new source type is created by deriving from the <g-source> structure. The derived type of source is represented by a structure that has the <g-source> structure as a first element, and other elements specific to the new source type. To create an instance of the new source type, call g-source-new passing in the size of the derived structure and a table of functions. These <g-source-funcs> determine the behavior of the new source types.

New source types basically interact with with the main context in two ways. Their prepare function in <g-source-funcs> can set a timeout to determine the maximum amount of time that the main loop will sleep before checking the source again. In addition, or as well, the source can add file descriptors to the set that the main context checks using g-source-add-poll.

5.3 Customizing the main loop iteration

Single iterations of a <g-main-context> can be run with g-main-context-iteration. In some cases, more detailed control of exactly how the details of the main loop work is desired, for instance, when integrating the <g-main-loop> with an external main loop. In such cases, you can call the component functions of g-main-context-iteration directly. These functions are g-main-context-prepare, g-main-context-query, g-main-context-check and g-main-context-dispatch.

The operation of these functions can best be seen in terms of a state diagram, as shown in (the missing figure, mainloop-states.

5.4 Usage

— Class: <g-main-loop>

Opaque pointer.

This class defines no direct slots.

— Class: <g-main-context>

Opaque pointer.

This class defines no direct slots.

— Class: <g-source>

Opaque pointer.

This class defines no direct slots.

— Function: g-main-loop-new (context <g-main-context>) (is_running bool) ⇒  (ret <g-main-loop>)

Creates a new <g-main-loop> structure.

context
a <g-main-context> (if ‘#f’, the default context will be used).
is-running
set to ‘#t’ to indicate that the loop is running. This is not very important since calling g-main-loop-run will set this to ‘#t’ anyway.
ret
a new <g-main-loop>.
— Function: g-main-loop-run (self <g-main-loop>)

Runs a main loop until g-main-loop-quit is called on the loop. If this is called for the thread of the loop's <g-main-context>, it will process events from the loop, otherwise it will simply wait.

loop
a <g-main-loop>
— Function: g-main-loop-quit (loop <g-main-loop>)

Stops a <g-main-loop> from running. Any calls to g-main-loop-run for the loop will return.

loop
a <g-main-loop>
— Function: g-main-loop-is-running (loop <g-main-loop>) ⇒  (ret bool)

Checks to see if the main loop is currently being run via g-main-loop-run.

loop
a <g-main-loop>.
ret
#t’ if the mainloop is currently being run.
— Function: g-main-loop-get-context (loop <g-main-loop>) ⇒  (ret <g-main-context>)

Returns the <g-main-context> of loop.

loop
a <g-main-loop>.
ret
the <g-main-context> of loop
— Function: g-main-context-new ⇒  (ret <g-main-context>)

Creates a new <g-main-context> strcuture

ret
the new <g-main-context>
— Function: g-main-context-default ⇒  (ret <g-main-context>)

Returns the default main context. This is the main context used for main loop functions when a main loop is not explicitly specified.

ret
the default main context.
— Function: g-main-context-iteration (self <g-main-context>) (may_block bool) ⇒  (ret bool)

Runs a single iteration for the given main loop. This involves checking to see if any event sources are ready to be processed, then if no events sources are ready and may-block is ‘#t’, waiting for a source to become ready, then dispatching the highest priority events sources that are ready. Note that even when may-block is ‘#t’, it is still possible for g-main-context-iteration to return ‘#f’, since the the wait may be interrupted for other reasons than an event source becoming ready.

context
a <g-main-context> (if ‘#f’, the default context will be used)
may-block
whether the call may block.
ret
#t’ if events were dispatched.
— Function: g-main-context-pending (context <g-main-context>) ⇒  (ret bool)

Checks if any sources have pending events for the given context.

context
a <g-main-context> (if ‘#f’, the default context will be used)
ret
#t’ if events are pending.
— Function: g-main-context-find-source-by-id (context <g-main-context>) (source_id unsigned-int) ⇒  (ret <g-source>)

Finds a <g-source> given a pair of context and ID.

context
a <g-main-context> (if ‘#f’, the default context will be used)
source-id
the source ID, as returned by g-source-get-id.
ret
the <g-source> if found, otherwise, ‘#f
— Function: g-main-context-wakeup (context <g-main-context>)

If context is currently waiting in a poll, interrupt the poll, and continue the iteration process.

context
a <g-main-context>
— Function: g-main-context-acquire (context <g-main-context>) ⇒  (ret bool)

Tries to become the owner of the specified context. If some other context is the owner of the context, returns ‘#f’ immediately. Ownership is properly recursive: the owner can require ownership again and will release ownership when g-main-context-release is called as many times as g-main-context-acquire.

You must be the owner of a context before you can call g-main-context-prepare, g-main-context-query, g-main-context-check, g-main-context-dispatch.

context
a <g-main-context>
ret
#t’ if the operation succeeded, and this thread is now the owner of context.
— Function: g-main-context-release (context <g-main-context>)

Releases ownership of a context previously acquired by this thread with g-main-context-acquire. If the context was acquired multiple times, the only release ownership when g-main-context-release is called as many times as it was acquired.

context
a <g-main-context>
— Function: g-main-context-is-owner (context <g-main-context>) ⇒  (ret bool)

Determines whether this thread holds the (recursive) ownership of this <g-maincontext>. This is useful to know before waiting on another thread that may be blocking to get ownership of context.

context
a <g-main-context>
ret
#t’ if current thread is owner of context.

Since 2.10

— Function: g-main-context-prepare (context <g-main-context>) ⇒  (ret bool) (priority int)

Prepares to poll sources within a main loop. The resulting information for polling is determined by calling g-main-context-query.

context
a <g-main-context>
priority
location to store priority of highest priority source already ready.
ret
#t’ if some source is ready to be dispatched prior to polling.
— Function: g-main-depth ⇒  (ret int)

Return value: The main loop recursion level in the current thread

The value returned is the depth of the stack of calls to g-main-context-dispatch on any <g-main-context> in the current thread. That is, when called from the toplevel, it gives 0. When called from within a callback from g-main-context-iteration (or g-main-loop-run, etc.) it returns 1. When called from within a callback to a recursive call to g-main-context-iterate, it returns 2. And so forth.

This function is an attractive nuisance, and its use normally indicates a misunderstanding of how main loop reentrancy works. Use gtk-widget-set-sensitive or modal dialogs to prevent the user from interacting with elements while the main loop is recursing.

A better idea is to avoid main loop recursion entirely. Instead, structure your code so that you simply return to the main loop and then get called again when there is more work to do.

— Function: g-main-current-source ⇒  (ret <g-source>)

Returns the currently firing source for this thread.

ret
The currently firing source or ‘#f’.

Since 2.12

— Function: g-timeout-source-new (interval unsigned-int) ⇒  (ret <g-source>)

Creates a new timeout source.

The source will not initially be associated with any <g-main-context> and must be added to one with g-source-attach before it will be executed.

interval
the timeout interval in milliseconds.
ret
the newly-created timeout source
— Function: g-idle-source-new ⇒  (ret <g-source>)

Creates a new idle source.

The source will not initially be associated with any <g-main-context> and must be added to one with g-source-attach before it will be executed. Note that the default priority for idle sources is ‘G_PRIORITY_DEFAULT_IDLE’, as compared to other sources which have a default priority of ‘G_PRIORITY_DEFAULT’.

ret
the newly-created idle source
— Function: g-child-watch-source-new (pid int) ⇒  (ret <g-source>)

Creates a new child_watch source.

The source will not initially be associated with any <g-main-context> and must be added to one with g-source-attach before it will be executed.

Note that child watch sources can only be used in conjunction with ‘g_spawn...’ when the ‘G_SPAWN_DO_NOT_REAP_CHILD’ flag is used.

Note that on platforms where <g-pid> must be explicitly closed (see g-spawn-close-pid) pid must not be closed while the source is still active. Typically, you will want to call g-spawn-close-pid in the callback function for the source.

Note further that using g-child-watch-source-new is not compatible with calling ‘waitpid(-1)’ in the application. Calling waitpid for individual pids will still work fine.

pid
process id of a child process to watch. On Windows, a HANDLE for the process to watch (which actually doesn't have to be a child).
ret
the newly-created child watch source

Since 2.4

— Function: g-source-attach (self <g-source>) (context <g-main-context>) ⇒  (ret unsigned-int)

Adds a <g-source> to a context so that it will be executed within that context.

source
a <g-source>
context
a <g-main-context> (if ‘#f’, the default context will be used)
ret
the ID (greater than 0) for the source within the <g-main-context>.
— Function: g-source-destroy (source <g-source>)

Removes a source from its <g-main-context>, if any, and mark it as destroyed. The source cannot be subsequently added to another context.

source
a <g-source>
— Function: g-source-is-destroyed (source <g-source>) ⇒  (ret bool)

Returns whether source has been destroyed.

This is important when you operate upon your objects from within idle handlers, but may have freed the object before the dispatch of your idle handler.

          
          static gboolean
          idle_callback (gpointer data)
          {
            SomeWidget *self = data;
          
            GDK_THREADS_ENTER ();
            /* do stuff with self */
            self->idle_id = 0;
            GDK_THREADS_LEAVE ();
          
            return FALSE;
          }
          
          static void
          some_widget_do_stuff_later (SomeWidget *self)
          {
            self->idle_id = g_idle_add (idle_callback, self);
          }
          
          static void
          some_widget_finalize (GObject *object)
          {
            SomeWidget *self = SOME_WIDGET (object);
          
            if (self->idle_id)
              g_source_remove (self->idle_id);
          
            G_OBJECT_CLASS (parent_class)->finalize (object);
          }

This will fail in a multi-threaded application if the widget is destroyed before the idle handler fires due to the use after free in the callback. A solution, to this particular problem, is to check to if the source has already been destroy within the callback.

          
          static gboolean
          idle_callback (gpointer data)
          {
            SomeWidget *self = data;
          
            GDK_THREADS_ENTER ();
            if (!g_source_is_destroyed (g_main_current_source ()))
              {
                /* do stuff with self */
              }
            GDK_THREADS_LEAVE ();
          
            return FALSE;
          }
source
a <g-source>
ret
#t’ if the source has been destroyed

Since 2.12

— Function: g-source-set-priority (source <g-source>) (priority int)

Sets the priority of a source. While the main loop is being run, a source will be dispatched if it is ready to be dispatched and no sources at a higher (numerically smaller) priority are ready to be dispatched.

source
a <g-source>
priority
the new priority.
— Function: g-source-get-priority (source <g-source>) ⇒  (ret int)

Gets the priority of a source.

source
a <g-source>
ret
the priority of the source
— Function: g-source-set-can-recurse (source <g-source>) (can_recurse bool)

Sets whether a source can be called recursively. If can-recurse is ‘#t’, then while the source is being dispatched then this source will be processed normally. Otherwise, all processing of this source is blocked until the dispatch function returns.

source
a <g-source>
can-recurse
whether recursion is allowed for this source
— Function: g-source-get-can-recurse (source <g-source>) ⇒  (ret bool)

Checks whether a source is allowed to be called recursively. see g-source-set-can-recurse.

source
a <g-source>
ret
whether recursion is allowed.
— Function: g-source-get-id (source <g-source>) ⇒  (ret unsigned-int)

Returns the numeric ID for a particular source. The ID of a source is a positive integer which is unique within a particular main loop context. The reverse mapping from ID to source is done by g-main-context-find-source-by-id.

source
a <g-source>
ret
the ID (greater than 0) for the source
— Function: g-source-get-context (source <g-source>) ⇒  (ret <g-main-context>)

Gets the <g-main-context> with which the source is associated. Calling this function on a destroyed source is an error.

source
a <g-source>
ret
the <g-main-context> with which the source is associated, or ‘#f’ if the context has not yet been added to a source.
— Function: g-source-remove (tag unsigned-int) ⇒  (ret bool)

Removes the source with the given id from the default main context. The id of a <g-source> is given by g-source-get-id, or will be returned by the functions g-source-attach, g-idle-add, g-idle-add-full, g-timeout-add, g-timeout-add-full, g-child-watch-add, g-child-watch-add-full, g-io-add-watch, and g-io-add-watch-full.

See also g-source-destroy.

tag
the ID of the source to remove.
ret
#t’ if the source was found and removed.