Relax g_thread_init() requirements

We now allow g_thread_init(NULL) to be called after other glib calls (with
some minor limitations). This is mainly a documentation change as this
really was already possible.

We also allow g_thread_init() to be called multiple times. Only the
first call actually initializes the threading system, further calls
are ignored (but print a warning if the argument is not NULL).

https://bugzilla.gnome.org/show_bug.cgi?id=606775
This commit is contained in:
Alexander Larsson 2010-01-12 21:16:59 +01:00
parent 74ad124cfb
commit 0df3ca8f9b
2 changed files with 24 additions and 36 deletions

View File

@ -33,25 +33,22 @@ primitives to portably create and manage threads (#GThread).
</para> </para>
<para> <para>
You must call g_thread_init() before executing any other GLib The threading system is initialized with g_thread_init(), which takes
functions (except g_mem_set_vtable()) in a GLib program if an optional custom thread implementation or %NULL for the default implementation.
g_thread_init() will be called at all. This is a requirement even if If you want to call g_thread_init() with a non-%NULL argument this must be done
no threads are in fact ever created by the process. It is enough that before executing any other GLib functions (except g_mem_set_vtable()). This is a
g_thread_init() is called. If other GLib functions have been called requirement even if no threads are in fact ever created by the process.
before that, the behaviour of the program is undefined. An exception </para>
is g_mem_set_vtable() which may be called before g_thread_init().
Failing this requirement can lead to hangs or crashes, apparently more <para>
easily on Windows than on Linux, for example. Calling g_thread_init() with a %NULL argument is somewhat more relaxed. You
may call any other glib functions in the main thread before g_thread_init() as
Please note that if you call functions in some GLib-using library, in long as g_thread_init() is not called from a glib callback, or with any locks held.
particular those above the GTK+ stack, that library might well call However, many libraries above glib does not support late initialization of
g_thread_init() itself, or call some other library that calls threads, so doing this should be avoided if possible.
g_thread_init(). Thus, if you use some GLib-based library that is </para>
above the GTK+ stack, it is safest to call g_thread_init() in your
application's main() before calling any GLib functions or functions in
GLib-using libraries.
<para>
After calling g_thread_init(), GLib is completely After calling g_thread_init(), GLib is completely
thread safe (all global data is automatically locked), but individual thread safe (all global data is automatically locked), but individual
data structure instances are not automatically locked for performance data structure instances are not automatically locked for performance
@ -198,24 +195,10 @@ may report unreliable times.
</para></note> </para></note>
<para> <para>
g_thread_init() might only be called once. On the second call Calling g_thread_init() multiple times is allowed (since version
it will abort with an error. If you want to make sure that the thread 2.24), but nothing happens except for the first call. If the argument
system is initialized, you can do this: is non-%NULL on such a call a warning will be printed, but otherwise
</para> the argument is ignored.
<para>
<informalexample>
<programlisting>
if (!g_thread_supported (<!-- -->)) g_thread_init (NULL);
</programlisting>
</informalexample>
</para>
<para>
After that line, either the thread system is initialized or, if no
thread system is available in GLib (i.e. either #G_THREADS_ENABLED is
not defined or #G_THREADS_IMPL_NONE is defined), the program will
abort.
</para> </para>
<para> <para>

View File

@ -294,7 +294,12 @@ g_thread_init (GThreadFunctions* init)
gboolean supported; gboolean supported;
if (thread_system_already_initialized) if (thread_system_already_initialized)
g_error ("GThread system may only be initialized once."); {
if (init != NULL)
g_warning ("GThread system already initialized, ignoring custom thread implementation.");
return;
}
thread_system_already_initialized = TRUE; thread_system_already_initialized = TRUE;