mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
parent
c3713e1b67
commit
0b56387ad5
@ -41,6 +41,7 @@ urlmap_file = "urlmap.js"
|
|||||||
# The same order will be used when generating the index
|
# The same order will be used when generating the index
|
||||||
content_files = [
|
content_files = [
|
||||||
"reference-counting.md",
|
"reference-counting.md",
|
||||||
|
"threads.md",
|
||||||
]
|
]
|
||||||
content_images = [
|
content_images = [
|
||||||
"Sorted_binary_tree_breadth-first_traversal.svg",
|
"Sorted_binary_tree_breadth-first_traversal.svg",
|
||||||
|
@ -153,6 +153,7 @@ endif
|
|||||||
# gi-docgen version
|
# gi-docgen version
|
||||||
expand_content_files = [
|
expand_content_files = [
|
||||||
'reference-counting.md',
|
'reference-counting.md',
|
||||||
|
'threads.md',
|
||||||
]
|
]
|
||||||
|
|
||||||
glib_gir = meson.current_source_dir() / 'GLib-2.0.gir'
|
glib_gir = meson.current_source_dir() / 'GLib-2.0.gir'
|
||||||
|
91
docs/reference/glib/threads.md
Normal file
91
docs/reference/glib/threads.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
Title: Threads
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
SPDX-FileCopyrightText: 2010 Allison Lortie
|
||||||
|
SPDX-FileCopyrightText: 2011, 2012, 2014 Matthias Clasen
|
||||||
|
SPDX-FileCopyrightText: 2014 Collabora, Ltd.
|
||||||
|
|
||||||
|
# Threads
|
||||||
|
|
||||||
|
Threads act almost like processes, but unlike processes all threads of one
|
||||||
|
process share the same memory. This is good, as it provides easy
|
||||||
|
communication between the involved threads via this shared memory, and it is
|
||||||
|
bad, because strange things (so called "Heisenbugs") might happen if the
|
||||||
|
program is not carefully designed. In particular, due to the concurrent
|
||||||
|
nature of threads, no assumptions on the order of execution of code running
|
||||||
|
in different threads can be made, unless order is explicitly forced by the
|
||||||
|
programmer through synchronization primitives.
|
||||||
|
|
||||||
|
The aim of the thread-related functions in GLib is to provide a portable
|
||||||
|
means for writing multi-threaded software. There are primitives for mutexes
|
||||||
|
to protect the access to portions of memory (`GMutex`, `GRecMutex` and
|
||||||
|
`GRWLock`). There is a facility to use individual bits for locks
|
||||||
|
(`g_bit_lock()`). There are primitives for condition variables to allow
|
||||||
|
synchronization of threads (`GCond`). There are primitives for
|
||||||
|
thread-private data - data that every thread has a private instance of
|
||||||
|
(`GPrivate`). There are facilities for one-time initialization (`GOnce`,
|
||||||
|
`g_once_init_enter_pointer()`, `g_once_init_enter()`). Finally, there are
|
||||||
|
primitives to create and manage threads (`GThread`).
|
||||||
|
|
||||||
|
The GLib threading system used to be initialized with `g_thread_init()`.
|
||||||
|
This is no longer necessary. Since version 2.32, the GLib threading system
|
||||||
|
is automatically initialized at the start of your program, and all
|
||||||
|
thread-creation functions and synchronization primitives are available right
|
||||||
|
away.
|
||||||
|
|
||||||
|
Note that it is not safe to assume that your program has no threads even if
|
||||||
|
you don't call `g_thread_new()` yourself. GLib and GIO can and will create
|
||||||
|
threads for their own purposes in some cases, such as when using
|
||||||
|
`g_unix_signal_source_new()` or when using GDBus.
|
||||||
|
|
||||||
|
Originally, UNIX did not have threads, and therefore some traditional UNIX
|
||||||
|
APIs are problematic in threaded programs. Some notable examples are
|
||||||
|
|
||||||
|
- C library functions that return data in statically allocated buffers, such
|
||||||
|
as `strtok()` or `strerror()`. For many of these, there are thread-safe
|
||||||
|
variants with a `_r` suffix, or you can look at corresponding GLib APIs
|
||||||
|
(`like g_strsplit()` or `g_strerror()`).
|
||||||
|
- The functions `setenv()` and `unsetenv()` manipulate the process
|
||||||
|
environment in a not thread-safe way, and may interfere with `getenv()`
|
||||||
|
calls in other threads. Note that `getenv()` calls may be hidden behind
|
||||||
|
other APIs. For example, GNU `gettext()` calls `getenv()` under the
|
||||||
|
covers. In general, it is best to treat the environment as readonly. If
|
||||||
|
you absolutely have to modify the environment, do it early in `main()`,
|
||||||
|
when no other threads are around yet.
|
||||||
|
- The `setlocale()` function changes the locale for the entire process,
|
||||||
|
affecting all threads. Temporary changes to the locale are often made to
|
||||||
|
change the behavior of string scanning or formatting functions like
|
||||||
|
`scanf()` or `printf()`. GLib offers a number of string APIs (like
|
||||||
|
`g_ascii_formatd()` or `g_ascii_strtod()`) that can often be used as an
|
||||||
|
alternative. Or you can use the `uselocale()` function to change the
|
||||||
|
locale only for the current thread.
|
||||||
|
- The `fork()` function only takes the calling thread into the child's copy
|
||||||
|
of the process image. If other threads were executing in critical sections
|
||||||
|
they could have left mutexes locked which could easily cause deadlocks in
|
||||||
|
the new child. For this reason, you should call `exit()` or `exec()` as
|
||||||
|
soon as possible in the child and only make signal-safe library calls
|
||||||
|
before that.
|
||||||
|
- The `daemon()` function uses `fork()` in a way contrary to what is
|
||||||
|
described above. It should not be used with GLib programs.
|
||||||
|
|
||||||
|
GLib itself is internally completely thread-safe (all global data is
|
||||||
|
automatically locked), but individual data structure instances are not
|
||||||
|
automatically locked for performance reasons. For example, you must
|
||||||
|
coordinate accesses to the same `GHashTable` from multiple threads. The two
|
||||||
|
notable exceptions from this rule are `GMainLoop` and `GAsyncQueue`, which are
|
||||||
|
thread-safe and need no further application-level locking to be accessed
|
||||||
|
from multiple threads. Most refcounting functions such as `g_object_ref()` are
|
||||||
|
also thread-safe.
|
||||||
|
|
||||||
|
A common use for GThreads is to move a long-running blocking operation out
|
||||||
|
of the main thread and into a worker thread. For GLib functions, such as
|
||||||
|
single GIO operations, this is not necessary, and complicates the code.
|
||||||
|
Instead, the `…_async()` version of the function should be used from the main
|
||||||
|
thread, eliminating the need for locking and synchronisation between
|
||||||
|
multiple threads. If an operation does need to be moved to a worker thread,
|
||||||
|
consider using `g_task_run_in_thread()`, or a `GThreadPool`. `GThreadPool` is
|
||||||
|
often a better choice than `GThread`, as it handles thread reuse and task
|
||||||
|
queueing; `GTask` uses this internally.
|
||||||
|
|
||||||
|
However, if multiple blocking operations need to be performed in sequence,
|
||||||
|
and it is not possible to use `GTask` for them, moving them to a worker thread
|
||||||
|
can clarify the code.
|
@ -62,105 +62,6 @@
|
|||||||
#include "glib_trace.h"
|
#include "glib_trace.h"
|
||||||
#include "gtrace-private.h"
|
#include "gtrace-private.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:threads
|
|
||||||
* @title: Threads
|
|
||||||
* @short_description: portable support for threads, mutexes, locks,
|
|
||||||
* conditions and thread private data
|
|
||||||
* @see_also: #GThreadPool, #GAsyncQueue
|
|
||||||
*
|
|
||||||
* Threads act almost like processes, but unlike processes all threads
|
|
||||||
* of one process share the same memory. This is good, as it provides
|
|
||||||
* easy communication between the involved threads via this shared
|
|
||||||
* memory, and it is bad, because strange things (so called
|
|
||||||
* "Heisenbugs") might happen if the program is not carefully designed.
|
|
||||||
* In particular, due to the concurrent nature of threads, no
|
|
||||||
* assumptions on the order of execution of code running in different
|
|
||||||
* threads can be made, unless order is explicitly forced by the
|
|
||||||
* programmer through synchronization primitives.
|
|
||||||
*
|
|
||||||
* The aim of the thread-related functions in GLib is to provide a
|
|
||||||
* portable means for writing multi-threaded software. There are
|
|
||||||
* primitives for mutexes to protect the access to portions of memory
|
|
||||||
* (#GMutex, #GRecMutex and #GRWLock). There is a facility to use
|
|
||||||
* individual bits for locks (g_bit_lock()). There are primitives
|
|
||||||
* for condition variables to allow synchronization of threads (#GCond).
|
|
||||||
* There are primitives for thread-private data - data that every
|
|
||||||
* thread has a private instance of (#GPrivate). There are facilities
|
|
||||||
* for one-time initialization (#GOnce, g_once_init_enter_pointer(),
|
|
||||||
* g_once_init_enter()). Finally,
|
|
||||||
* there are primitives to create and manage threads (#GThread).
|
|
||||||
*
|
|
||||||
* The GLib threading system used to be initialized with g_thread_init().
|
|
||||||
* This is no longer necessary. Since version 2.32, the GLib threading
|
|
||||||
* system is automatically initialized at the start of your program,
|
|
||||||
* and all thread-creation functions and synchronization primitives
|
|
||||||
* are available right away.
|
|
||||||
*
|
|
||||||
* Note that it is not safe to assume that your program has no threads
|
|
||||||
* even if you don't call g_thread_new() yourself. GLib and GIO can
|
|
||||||
* and will create threads for their own purposes in some cases, such
|
|
||||||
* as when using g_unix_signal_source_new() or when using GDBus.
|
|
||||||
*
|
|
||||||
* Originally, UNIX did not have threads, and therefore some traditional
|
|
||||||
* UNIX APIs are problematic in threaded programs. Some notable examples
|
|
||||||
* are
|
|
||||||
*
|
|
||||||
* - C library functions that return data in statically allocated
|
|
||||||
* buffers, such as strtok() or strerror(). For many of these,
|
|
||||||
* there are thread-safe variants with a _r suffix, or you can
|
|
||||||
* look at corresponding GLib APIs (like g_strsplit() or g_strerror()).
|
|
||||||
*
|
|
||||||
* - The functions setenv() and unsetenv() manipulate the process
|
|
||||||
* environment in a not thread-safe way, and may interfere with getenv()
|
|
||||||
* calls in other threads. Note that getenv() calls may be hidden behind
|
|
||||||
* other APIs. For example, GNU gettext() calls getenv() under the
|
|
||||||
* covers. In general, it is best to treat the environment as readonly.
|
|
||||||
* If you absolutely have to modify the environment, do it early in
|
|
||||||
* main(), when no other threads are around yet.
|
|
||||||
*
|
|
||||||
* - The setlocale() function changes the locale for the entire process,
|
|
||||||
* affecting all threads. Temporary changes to the locale are often made
|
|
||||||
* to change the behavior of string scanning or formatting functions
|
|
||||||
* like scanf() or printf(). GLib offers a number of string APIs
|
|
||||||
* (like g_ascii_formatd() or g_ascii_strtod()) that can often be
|
|
||||||
* used as an alternative. Or you can use the uselocale() function
|
|
||||||
* to change the locale only for the current thread.
|
|
||||||
*
|
|
||||||
* - The fork() function only takes the calling thread into the child's
|
|
||||||
* copy of the process image. If other threads were executing in critical
|
|
||||||
* sections they could have left mutexes locked which could easily
|
|
||||||
* cause deadlocks in the new child. For this reason, you should
|
|
||||||
* call exit() or exec() as soon as possible in the child and only
|
|
||||||
* make signal-safe library calls before that.
|
|
||||||
*
|
|
||||||
* - The daemon() function uses fork() in a way contrary to what is
|
|
||||||
* described above. It should not be used with GLib programs.
|
|
||||||
*
|
|
||||||
* GLib itself is internally completely thread-safe (all global data is
|
|
||||||
* automatically locked), but individual data structure instances are
|
|
||||||
* not automatically locked for performance reasons. For example,
|
|
||||||
* you must coordinate accesses to the same #GHashTable from multiple
|
|
||||||
* threads. The two notable exceptions from this rule are #GMainLoop
|
|
||||||
* and #GAsyncQueue, which are thread-safe and need no further
|
|
||||||
* application-level locking to be accessed from multiple threads.
|
|
||||||
* Most refcounting functions such as g_object_ref() are also thread-safe.
|
|
||||||
*
|
|
||||||
* A common use for #GThreads is to move a long-running blocking operation out
|
|
||||||
* of the main thread and into a worker thread. For GLib functions, such as
|
|
||||||
* single GIO operations, this is not necessary, and complicates the code.
|
|
||||||
* Instead, the `…_async()` version of the function should be used from the main
|
|
||||||
* thread, eliminating the need for locking and synchronisation between multiple
|
|
||||||
* threads. If an operation does need to be moved to a worker thread, consider
|
|
||||||
* using g_task_run_in_thread(), or a #GThreadPool. #GThreadPool is often a
|
|
||||||
* better choice than #GThread, as it handles thread reuse and task queueing;
|
|
||||||
* #GTask uses this internally.
|
|
||||||
*
|
|
||||||
* However, if multiple blocking operations need to be performed in sequence,
|
|
||||||
* and it is not possible to use #GTask for them, moving them to a worker thread
|
|
||||||
* can clarify the code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* G_LOCK Documentation {{{1 ---------------------------------------------- */
|
/* G_LOCK Documentation {{{1 ---------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user