mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 05:56:14 +01:00
parent
6c6337aa27
commit
d8b25ecda3
@ -47,11 +47,13 @@ content_files = [
|
||||
"conversion-macros.md",
|
||||
"error-reporting.md",
|
||||
"logging.md",
|
||||
"main-loop.md",
|
||||
"reference-counting.md",
|
||||
"threads.md",
|
||||
]
|
||||
content_images = [
|
||||
"file-name-encodings.png",
|
||||
"mainloop-states.gif",
|
||||
"Sorted_binary_tree_breadth-first_traversal.svg",
|
||||
"Sorted_binary_tree_inorder.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.
|
||||
|
||||
![](mainloop-states.gif)
|
||||
|
||||
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',
|
||||
'i18n.md',
|
||||
'logging.md',
|
||||
'main-loop.md',
|
||||
'reference-counting.md',
|
||||
'threads.md',
|
||||
]
|
||||
|
128
glib/gmain.c
128
glib/gmain.c
@ -127,134 +127,6 @@
|
||||
#include "glib-init.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.
|
||||
*
|
||||
* ![](mainloop-states.gif)
|
||||
*
|
||||
* 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 */
|
||||
|
||||
typedef struct _GIdleSource GIdleSource;
|
||||
|
Loading…
Reference in New Issue
Block a user