mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-12 04:04:04 +02:00
committed by
Philip Withnall
parent
6c6337aa27
commit
d8b25ecda3
@@ -47,11 +47,13 @@ content_files = [
|
|||||||
"conversion-macros.md",
|
"conversion-macros.md",
|
||||||
"error-reporting.md",
|
"error-reporting.md",
|
||||||
"logging.md",
|
"logging.md",
|
||||||
|
"main-loop.md",
|
||||||
"reference-counting.md",
|
"reference-counting.md",
|
||||||
"threads.md",
|
"threads.md",
|
||||||
]
|
]
|
||||||
content_images = [
|
content_images = [
|
||||||
"file-name-encodings.png",
|
"file-name-encodings.png",
|
||||||
|
"mainloop-states.gif",
|
||||||
"Sorted_binary_tree_breadth-first_traversal.svg",
|
"Sorted_binary_tree_breadth-first_traversal.svg",
|
||||||
"Sorted_binary_tree_inorder.svg",
|
"Sorted_binary_tree_inorder.svg",
|
||||||
"Sorted_binary_tree_postorder.svg",
|
"Sorted_binary_tree_postorder.svg",
|
||||||
|
107
docs/reference/glib/main-loop.md
Normal file
107
docs/reference/glib/main-loop.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
Title: The Main Event Loop
|
||||||
|
|
||||||
|
# The Main Event Loop
|
||||||
|
|
||||||
|
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 `GMainContext`. A `GMainContext`
|
||||||
|
can only be running in a single thread, but sources can be added to it and
|
||||||
|
removed from it from other threads. All functions which operate on a
|
||||||
|
`GMainContext` or a built-in `GSource` are thread-safe.
|
||||||
|
|
||||||
|
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 `GMainLoop` data type represents a main event loop. A GMainLoop 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 `GMainLoop` recursively. This is
|
||||||
|
often used in GTK applications when showing modal dialog boxes. Note that
|
||||||
|
event sources are associated with a particular `GMainContext`, and will be
|
||||||
|
checked and dispatched for all main loops associated with that GMainContext.
|
||||||
|
|
||||||
|
Libraries may contain wrappers of some of these functions, e.g.
|
||||||
|
`gtk_main()`, `gtk_main_quit()` and `gtk_events_pending()`.
|
||||||
|
|
||||||
|
## Creating new source types
|
||||||
|
|
||||||
|
One of the unusual features of the `GMainLoop` 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 `GSource`
|
||||||
|
structure. The derived type of source is represented by a structure that has
|
||||||
|
the `GSource` 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 `GSourceFuncs` determine the behavior of the new source
|
||||||
|
type.
|
||||||
|
|
||||||
|
New source types basically interact with the main context in two ways. Their
|
||||||
|
prepare function in `GSourceFuncs` 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()`.
|
||||||
|
|
||||||
|
## Customizing the main loop iteration
|
||||||
|
|
||||||
|
Single iterations of a `GMainContext` 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 `GMainLoop` 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()`.
|
||||||
|
|
||||||
|
## State of a Main Context
|
||||||
|
|
||||||
|
The operation of these functions can best be seen in terms of a state
|
||||||
|
diagram, as shown in this image.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
On UNIX, the GLib mainloop is incompatible with `fork()`. Any program using
|
||||||
|
the mainloop must either `exec()` or `exit()` from the child without
|
||||||
|
returning to the mainloop.
|
||||||
|
|
||||||
|
## Memory management of sources
|
||||||
|
|
||||||
|
There are two options for memory management of the user data passed to a
|
||||||
|
`GSource` to be passed to its callback on invocation. This data is provided
|
||||||
|
in calls to `g_timeout_add()`, `g_timeout_add_full()`, `g_idle_add()`, etc.
|
||||||
|
and more generally, using `g_source_set_callback()`. This data is typically
|
||||||
|
an object which ‘owns’ the timeout or idle callback, such as a widget or a
|
||||||
|
network protocol implementation. In many cases, it is an error for the
|
||||||
|
callback to be invoked after this owning object has been destroyed, as that
|
||||||
|
results in use of freed memory.
|
||||||
|
|
||||||
|
The first, and preferred, option is to store the source ID returned by
|
||||||
|
functions such as `g_timeout_add()` or `g_source_attach()`, and explicitly
|
||||||
|
remove that source from the main context using `g_source_remove()` when the
|
||||||
|
owning object is finalized. This ensures that the callback can only be
|
||||||
|
invoked while the object is still alive.
|
||||||
|
|
||||||
|
The second option is to hold a strong reference to the object in the
|
||||||
|
callback, and to release it in the callback’s `GDestroyNotify`. This ensures
|
||||||
|
that the object is kept alive until after the source is finalized, which is
|
||||||
|
guaranteed to be after it is invoked for the final time. The
|
||||||
|
`GDestroyNotify` is another callback passed to the ‘full’ variants of
|
||||||
|
`GSource` functions (for example, `g_timeout_add_full()`). It is called when
|
||||||
|
the source is finalized, and is designed for releasing references like this.
|
||||||
|
|
||||||
|
One important caveat of this second approach is that it will keep the object
|
||||||
|
alive indefinitely if the main loop is stopped before the `GSource` is
|
||||||
|
invoked, which may be undesirable.
|
@@ -156,6 +156,7 @@ expand_content_files = [
|
|||||||
'error-reporting.md',
|
'error-reporting.md',
|
||||||
'i18n.md',
|
'i18n.md',
|
||||||
'logging.md',
|
'logging.md',
|
||||||
|
'main-loop.md',
|
||||||
'reference-counting.md',
|
'reference-counting.md',
|
||||||
'threads.md',
|
'threads.md',
|
||||||
]
|
]
|
||||||
|
128
glib/gmain.c
128
glib/gmain.c
@@ -127,134 +127,6 @@
|
|||||||
#include "glib-init.h"
|
#include "glib-init.h"
|
||||||
#include "glib-private.h"
|
#include "glib-private.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:main
|
|
||||||
* @title: The Main Event Loop
|
|
||||||
* @short_description: manages all available sources of events
|
|
||||||
*
|
|
||||||
* 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 #GMainContext.
|
|
||||||
* A #GMainContext can only be running in a single thread, but
|
|
||||||
* sources can be added to it and removed from it from other threads. All
|
|
||||||
* functions which operate on a #GMainContext or a built-in #GSource are
|
|
||||||
* thread-safe.
|
|
||||||
*
|
|
||||||
* 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: if
|
|
||||||
* several sources are ready to dispatch, the ones with equal-highest priority
|
|
||||||
* will be dispatched on the current #GMainContext iteration, and the rest wait
|
|
||||||
* until a subsequent #GMainContext iteration when they have the highest
|
|
||||||
* priority of the sources which are ready for dispatch.
|
|
||||||
*
|
|
||||||
* 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 dispatched.
|
|
||||||
*
|
|
||||||
* The #GMainLoop data type represents a main event loop. A GMainLoop 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 #GMainLoop recursively.
|
|
||||||
* This is often used in GTK applications when showing modal dialog
|
|
||||||
* boxes. Note that event sources are associated with a particular
|
|
||||||
* #GMainContext, and will be checked and dispatched for all main
|
|
||||||
* loops associated with that GMainContext.
|
|
||||||
*
|
|
||||||
* GTK contains wrappers of some of these functions, e.g. gtk_main(),
|
|
||||||
* gtk_main_quit() and gtk_events_pending().
|
|
||||||
*
|
|
||||||
* ## Creating new source types
|
|
||||||
*
|
|
||||||
* One of the unusual features of the #GMainLoop 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 #GSource structure. The derived type of
|
|
||||||
* source is represented by a structure that has the #GSource 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 #GSourceFuncs determine the behavior of
|
|
||||||
* the new source type.
|
|
||||||
*
|
|
||||||
* New source types basically interact with the main context
|
|
||||||
* in two ways. Their prepare function in #GSourceFuncs 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().
|
|
||||||
*
|
|
||||||
* ## Customizing the main loop iteration
|
|
||||||
*
|
|
||||||
* Single iterations of a #GMainContext 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 #GMainLoop 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().
|
|
||||||
*
|
|
||||||
* If the event loop thread releases #GMainContext ownership until the results
|
|
||||||
* required by g_main_context_check() are ready you must create a context with
|
|
||||||
* the flag %G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING or else you'll lose
|
|
||||||
* g_source_attach() notifications. This happens for instance when you integrate
|
|
||||||
* the GLib event loop into implementations that follow the proactor pattern
|
|
||||||
* (i.e. in these contexts the `poll()` implementation will reclaim the thread for
|
|
||||||
* other tasks until the results are ready). One example of the proactor pattern
|
|
||||||
* is the Boost.Asio library.
|
|
||||||
*
|
|
||||||
* ## State of a Main Context # {#mainloop-states}
|
|
||||||
*
|
|
||||||
* The operation of these functions can best be seen in terms
|
|
||||||
* of a state diagram, as shown in this image.
|
|
||||||
*
|
|
||||||
* 
|
|
||||||
*
|
|
||||||
* On UNIX, the GLib mainloop is incompatible with fork(). Any program
|
|
||||||
* using the mainloop must either exec() or exit() from the child
|
|
||||||
* without returning to the mainloop.
|
|
||||||
*
|
|
||||||
* ## Memory management of sources # {#mainloop-memory-management}
|
|
||||||
*
|
|
||||||
* There are two options for memory management of the user data passed to a
|
|
||||||
* #GSource to be passed to its callback on invocation. This data is provided
|
|
||||||
* in calls to g_timeout_add(), g_timeout_add_full(), g_idle_add(), etc. and
|
|
||||||
* more generally, using g_source_set_callback(). This data is typically an
|
|
||||||
* object which ‘owns’ the timeout or idle callback, such as a widget or a
|
|
||||||
* network protocol implementation. In many cases, it is an error for the
|
|
||||||
* callback to be invoked after this owning object has been destroyed, as that
|
|
||||||
* results in use of freed memory.
|
|
||||||
*
|
|
||||||
* The first, and preferred, option is to store the source ID returned by
|
|
||||||
* functions such as g_timeout_add() or g_source_attach(), and explicitly
|
|
||||||
* remove that source from the main context using g_source_remove() when the
|
|
||||||
* owning object is finalized. This ensures that the callback can only be
|
|
||||||
* invoked while the object is still alive.
|
|
||||||
*
|
|
||||||
* The second option is to hold a strong reference to the object in the
|
|
||||||
* callback, and to release it in the callback’s #GDestroyNotify. This ensures
|
|
||||||
* that the object is kept alive until after the source is finalized, which is
|
|
||||||
* guaranteed to be after it is invoked for the final time. The #GDestroyNotify
|
|
||||||
* is another callback passed to the ‘full’ variants of #GSource functions (for
|
|
||||||
* example, g_timeout_add_full()). It is called when the source is finalized,
|
|
||||||
* and is designed for releasing references like this.
|
|
||||||
*
|
|
||||||
* One important caveat of this second approach is that it will keep the object
|
|
||||||
* alive indefinitely if the main loop is stopped before the #GSource is
|
|
||||||
* invoked, which may be undesirable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
|
|
||||||
typedef struct _GIdleSource GIdleSource;
|
typedef struct _GIdleSource GIdleSource;
|
||||||
|
Reference in New Issue
Block a user