Allow g_thread_init() to be called multiple times, and to call glib
functions before that one is called.

This consists of the following commits from upstream:

3c5e1fd Remove additional thread support in performance test
3bb404f Mention thread changes in NEWS
94b8613 Use unconditional thread calls in gio and gobject
de5c708 Make thread calls unconditional if G_THREADS_MANDATORY is set
fa2bced Enable threads in g_type_init()
0df3ca8 Relax g_thread_init() requirements


diff --git a/README.in b/README.in
index 911995e..971e03c 100644
--- a/README.in
+++ b/README.in
@@ -24,6 +24,16 @@ Installation
 
 See the file 'INSTALL'
 
+Notes about GLib 2.24
+=====================
+* It is now allowed to call g_thread_init(NULL) multiple times, and
+  to call glib functions before g_thread_init(NULL) is called
+  (although the later is mainly a change in docs as this worked before
+  too). See the GThread reference documentation for the details.
+
+* GObject now links to GThread and threads are enabled automatically
+  when g_type_init() is called.
+
 Notes about GLib 2.22
 =====================
 
diff --git a/configure.in b/configure.in
index f5e7430..f731b66 100644
--- a/configure.in
+++ b/configure.in
@@ -2337,6 +2337,7 @@ case $host in
     ;;
 esac
 
+AM_CONDITIONAL(HAVE_THREADS, [test "$have_threads" != "none"])
 AC_DEFINE_UNQUOTED(G_THREAD_SOURCE,"gthread-$have_threads.c",
 		   [Source file containing theread implementation])
 AC_SUBST(G_THREAD_CFLAGS)
diff --git a/docs/reference/glib/tmpl/threads.sgml b/docs/reference/glib/tmpl/threads.sgml
index 58c62bd..feb9399 100644
--- a/docs/reference/glib/tmpl/threads.sgml
+++ b/docs/reference/glib/tmpl/threads.sgml
@@ -33,25 +33,30 @@ primitives to portably create and manage threads (#GThread).
 </para>
 
 <para>
-You must call g_thread_init() before executing any other GLib
-functions (except g_mem_set_vtable()) in a GLib program if
-g_thread_init() will be called at all. This is a requirement even if
-no threads are in fact ever created by the process. It is enough that
-g_thread_init() is called. If other GLib functions have been called
-before that, the behaviour of the program is undefined. An exception
-is g_mem_set_vtable() which may be called before g_thread_init().
-
-Failing this requirement can lead to hangs or crashes, apparently more
-easily on Windows than on Linux, for example.
-
-Please note that if you call functions in some GLib-using library, in
-particular those above the GTK+ stack, that library might well call
-g_thread_init() itself, or call some other library that calls
-g_thread_init(). Thus, if you use some GLib-based library that is
-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.
+The threading system is initialized with g_thread_init(), which takes
+an optional custom thread implementation or %NULL for the default implementation.
+If you want to call g_thread_init() with a non-%NULL argument this must be done
+before executing any other GLib functions (except g_mem_set_vtable()). This is a
+requirement even if no threads are in fact ever created by the process.
+</para>
 
+<para>
+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
+long as g_thread_init() is not called from a glib callback, or with any locks held.
+However, many libraries above glib does not support late initialization of
+threads, so doing this should be avoided if possible.
+</para>
+
+<para>
+Please note that since version 2.24 the GObject initialization
+function g_type_init() initializes threads (with a %NULL argument), so
+most applications, including those using Gtk+ will run with threads
+enabled. If you want a special thread implementation, make sure you
+call g_thread_init() before g_type_init() is called.
+</para>
+
+<para>
 After calling g_thread_init(), GLib is completely
 thread safe (all global data is automatically locked), but individual
 data structure instances are not automatically locked for performance
@@ -198,24 +203,10 @@ may report unreliable times.
 </para></note>
 
 <para>
-g_thread_init() might only be called once. On the second call
-it will abort with an error. If you want to make sure that the thread
-system is initialized, you can do this:
-</para>
-
-<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.
+Calling g_thread_init() multiple times is allowed (since version
+2.24), but nothing happens except for the first call. If the argument
+is non-%NULL on such a call a warning will be printed, but otherwise
+the argument is ignored.
 </para>
 
 <para>
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 383fa8f..971c380 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -41,6 +41,10 @@ TESTS = abicheck.sh pltcheck.sh
 endif
 endif
 
+if HAVE_THREADS
+THREAD_FLAGS=-DG_THREADS_MANDATORY
+endif
+
 AM_CPPFLAGS = \
 	-DG_LOG_DOMAIN=\"GLib-GIO\"			\
 	-I$(top_builddir)				\
@@ -48,6 +52,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/glib				\
 	-I$(top_srcdir)/gmodule				\
 	$(GLIB_DEBUG_FLAGS)				\
+	$(THREAD_FLAGS)					\
 	-DG_DISABLE_DEPRECATED				\
 	-DGIO_COMPILATION				\
 	-DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"	
diff --git a/glib/gthread.h b/glib/gthread.h
index 019d0db..7a0abba 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -198,7 +198,11 @@ GMutex* g_static_mutex_get_mutex_impl   (GMutex **mutex);
           (cond, mutex, abs_time, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : TRUE)
 #endif /* G_ERRORCHECK_MUTEXES */
 
+#if defined(G_THREADS_ENABLED) && defined(G_THREADS_MANDATORY)
+#define g_thread_supported()     1
+#else
 #define g_thread_supported()    (g_threads_got_initialized)
+#endif
 #define g_mutex_new()            G_THREAD_UF (mutex_new,      ())
 #define g_cond_new()             G_THREAD_UF (cond_new,       ())
 #define g_cond_signal(cond)      G_THREAD_CF (cond_signal,    (void)0, (cond))
diff --git a/gobject-2.0-uninstalled.pc.in b/gobject-2.0-uninstalled.pc.in
index 1aab1b5..d9378a5 100644
--- a/gobject-2.0-uninstalled.pc.in
+++ b/gobject-2.0-uninstalled.pc.in
@@ -1,6 +1,6 @@
 Name: GObject Uninstalled
 Description: Object/type system for GLib, Not Installed
-Requires: glib-2.0-uninstalled
+Requires: glib-2.0-uninstalled,gthread-2.0-uninstalled
 Version: @VERSION@
 Libs: ${pc_top_builddir}/${pcfiledir}/gobject/libgobject-2.0.la
 ## cflags contains builddir in addition to srcdir because of gmarshal.h
diff --git a/gobject-2.0.pc.in b/gobject-2.0.pc.in
index 31fe34d..41505a9 100644
--- a/gobject-2.0.pc.in
+++ b/gobject-2.0.pc.in
@@ -5,7 +5,7 @@ includedir=@includedir@
 
 Name: GObject
 Description: GLib Type, Object, Parameter and Signal Library
-Requires: glib-2.0
+Requires: glib-2.0,gthread-2.0
 Version: @VERSION@
 Libs: -L${libdir} -lgobject-2.0
 Cflags:
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
index 8ec4ee7..f59cc3c 100644
--- a/gobject/Makefile.am
+++ b/gobject/Makefile.am
@@ -6,12 +6,17 @@ include $(top_srcdir)/Makefile.decl
 
 SUBDIRS = . tests
 
+if HAVE_THREADS
+THREAD_FLAGS=-DG_THREADS_MANDATORY
+endif
+
 AM_CPPFLAGS = 					\
 	-DG_LOG_DOMAIN=\"GLib-GObject\"		\
 	-I$(top_srcdir)				\
 	-I$(top_srcdir)/glib			\
 	-I$(top_builddir)			\
 	$(GLIB_DEBUG_FLAGS)			\
+	$(THREAD_FLAGS)				\
 	-DG_DISABLE_DEPRECATED			\
 	-DGOBJECT_COMPILATION			\
 	-DG_DISABLE_CONST_RETURNS
@@ -31,7 +36,7 @@ TESTS = abicheck.sh pltcheck.sh
 endif
 endif
 
-libglib = $(top_builddir)/glib/libglib-2.0.la
+libglib = $(top_builddir)/glib/libglib-2.0.la $(top_builddir)/gthread/libgthread-2.0.la
 
 # libraries to compile and install
 lib_LTLIBRARIES = libgobject-2.0.la
diff --git a/gobject/gtype.c b/gobject/gtype.c
index a782ce7..05431e7 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -4027,7 +4027,12 @@ g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
   GTypeInfo info;
   TypeNode *node;
   volatile GType votype;
-  
+
+#ifdef G_THREADS_ENABLED
+  if (!g_thread_get_initialized())
+    g_thread_init (NULL);
+#endif
+
   G_LOCK (type_init_lock);
   
   G_WRITE_LOCK (&type_rw_lock);
@@ -4131,6 +4136,8 @@ g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
  * to initialize the type system and assorted other code portions
  * (such as the various fundamental type implementations or the signal
  * system).
+ *
+ * Since version 2.24 this also initializes the thread system
  */
 void
 g_type_init (void)
diff --git a/gthread/gthread-impl.c b/gthread/gthread-impl.c
index 24eb3c4..f0f2be0 100644
--- a/gthread/gthread-impl.c
+++ b/gthread/gthread-impl.c
@@ -294,7 +294,12 @@ g_thread_init (GThreadFunctions* init)
   gboolean supported;
 
   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;
 
diff --git a/tests/gobject/performance.c b/tests/gobject/performance.c
index 6f1b5d0..c626916 100644
--- a/tests/gobject/performance.c
+++ b/tests/gobject/performance.c
@@ -32,14 +32,11 @@
 #define TARGET_ROUND_TIME 0.004
 
 static gboolean verbose = FALSE;
-static gboolean init_threads = FALSE;
 static int test_length = DEFAULT_TEST_TIME;
 
 static GOptionEntry cmd_entries[] = {
   {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
    "Print extra information", NULL},
-  {"threads", 't', 0, G_OPTION_ARG_NONE, &init_threads,
-   "Initialize threads", NULL},
   {"seconds", 's', 0, G_OPTION_ARG_INT, &test_length,
    "Time to run each test in seconds", NULL},
   {NULL}
@@ -713,9 +710,6 @@ main (int   argc,
       return 1;
     }
 
-  if (init_threads)
-    g_thread_init (NULL);
-
   if (argc > 1)
     {
       for (i = 1; i < argc; i++)
