[glib] Deprecate GStaticPrivate and g_thread_foreach



commit 3d4846d92309d001697c2827660fa41b5c63dbc4
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Oct 2 01:29:08 2011 -0400

    Deprecate GStaticPrivate and g_thread_foreach
    
    This commit moves GStaticPrivate, g_thread_foreach and all
    related functions and variables to gthread-deprecated.c. We
    introduce some internal API to make this possible.
    
    g_thread_foreach is not a very useful function, since there is
    virtually nothing you can do with a GThread*, and implementing
    it requires us to keep a list of threads around.
    
    GStaticPrivate has been made redundant by adding comparable
    capabilities to GPrivate.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=660635

 glib/deprecated/gthread-deprecated.c |  324 +++++++++++++++++++++++++++++++-
 glib/deprecated/gthread.h            |   18 ++-
 glib/gthread.c                       |  348 +--------------------------------
 glib/gthread.h                       |   16 --
 glib/gthreadprivate.h                |   20 ++
 5 files changed, 371 insertions(+), 355 deletions(-)
---
diff --git a/glib/deprecated/gthread-deprecated.c b/glib/deprecated/gthread-deprecated.c
index dabab8d..22f4a76 100644
--- a/glib/deprecated/gthread-deprecated.c
+++ b/glib/deprecated/gthread-deprecated.c
@@ -109,6 +109,14 @@ gettime (void)
 
 guint64 (*g_thread_gettime) (void) = gettime;
 
+/* Internal variables {{{1 */
+
+static GRealThread *g_thread_all_threads = NULL;
+static GSList      *g_thread_free_indices = NULL;
+
+/* Protects g_thread_all_threads and g_thread_free_indices */
+G_LOCK_DEFINE_STATIC (g_thread);
+
 /* Misc. GThread functions {{{1 */
 
 /**
@@ -186,6 +194,88 @@ g_thread_create_full (GThreadFunc       func,
   return g_thread_new_internal (NULL, func, data, joinable, stack_size, TRUE, error);
 }
 
+/**
+ * g_thread_foreach:
+ * @thread_func: function to call for all #GThread structures
+ * @user_data: second argument to @thread_func
+ *
+ * Call @thread_func on all #GThreads that have been
+ * created with g_thread_create().
+ *
+ * Note that threads may decide to exit while @thread_func is
+ * running, so without intimate knowledge about the lifetime of
+ * foreign threads, @thread_func shouldn't access the GThread*
+ * pointer passed in as first argument. However, @thread_func will
+ * not be called for threads which are known to have exited already.
+ *
+ * Due to thread lifetime checks, this function has an execution complexity
+ * which is quadratic in the number of existing threads.
+ *
+ * Since: 2.10
+ *
+ * Deprecated:2.32: There are not very many interesting things you can
+ *     do with a #GThread, except comparing it with one that was returned
+ *     from g_thread_create(). There are better ways to find out if your
+ *     thread is still alive.
+ */
+void
+g_thread_foreach (GFunc    thread_func,
+                  gpointer user_data)
+{
+  GSList *slist = NULL;
+  GRealThread *thread;
+  g_return_if_fail (thread_func != NULL);
+  /* snapshot the list of threads for iteration */
+  G_LOCK (g_thread);
+  for (thread = g_thread_all_threads; thread; thread = thread->next)
+    slist = g_slist_prepend (slist, thread);
+  G_UNLOCK (g_thread);
+  /* walk the list, skipping non-existent threads */
+  while (slist)
+    {
+      GSList *node = slist;
+      slist = node->next;
+      /* check whether the current thread still exists */
+      G_LOCK (g_thread);
+      for (thread = g_thread_all_threads; thread; thread = thread->next)
+        if (thread == node->data)
+          break;
+      G_UNLOCK (g_thread);
+      if (thread)
+        thread_func (thread, user_data);
+      g_slist_free_1 (node);
+    }
+}
+
+void
+g_enumerable_thread_add (GRealThread *thread)
+{
+  G_LOCK (g_thread);
+  thread->next = g_thread_all_threads;
+  g_thread_all_threads = thread;
+  G_UNLOCK (g_thread);
+}
+
+void
+g_enumerable_thread_remove (GRealThread *thread)
+{
+  GRealThread *t, *p;
+
+  G_LOCK (g_thread);
+  for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+    {
+      if (t == thread)
+        {
+          if (p)
+            p->next = t->next;
+          else
+            g_thread_all_threads = t->next;
+          break;
+        }
+    }
+  G_UNLOCK (g_thread);
+}
+
 /* GStaticMutex {{{1 ------------------------------------------------------ */
 
 /**
@@ -1029,5 +1119,237 @@ g_private_new (GDestroyNotify notify)
   return key;
 }
 
-/* Epilogue {{{1 */
+/* {{{1 GStaticPrivate */
+
+typedef struct _GStaticPrivateNode GStaticPrivateNode;
+struct _GStaticPrivateNode
+{
+  gpointer        data;
+  GDestroyNotify  destroy;
+  GStaticPrivate *owner;
+};
+
+/**
+ * GStaticPrivate:
+ *
+ * A #GStaticPrivate works almost like a #GPrivate, but it has one
+ * significant advantage. It doesn't need to be created at run-time
+ * like a #GPrivate, but can be defined at compile-time. This is
+ * similar to the difference between #GMutex and #GStaticMutex. Now
+ * look at our <function>give_me_next_number()</function> example with
+ * #GStaticPrivate:
+ *
+ * <example>
+ *  <title>Using GStaticPrivate for per-thread data</title>
+ *  <programlisting>
+ *   int
+ *   give_me_next_number (<!-- -->)
+ *   {
+ *     static GStaticPrivate current_number_key = G_STATIC_PRIVATE_INIT;
+ *     int *current_number = g_static_private_get (&amp;current_number_key);
+ *
+ *     if (!current_number)
+ *       {
+ *         current_number = g_new (int,1);
+ *         *current_number = 0;
+ *         g_static_private_set (&amp;current_number_key, current_number, g_free);
+ *       }
+ *
+ *     *current_number = calc_next_number (*current_number);
+ *
+ *     return *current_number;
+ *   }
+ *  </programlisting>
+ * </example>
+ */
+
+/**
+ * G_STATIC_PRIVATE_INIT:
+ *
+ * Every #GStaticPrivate must be initialized with this macro, before it
+ * can be used.
+ *
+ * |[
+ *   GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
+ * ]|
+ */
+
+/**
+ * g_static_private_init:
+ * @private_key: a #GStaticPrivate to be initialized
+ *
+ * Initializes @private_key. Alternatively you can initialize it with
+ * #G_STATIC_PRIVATE_INIT.
+ */
+void
+g_static_private_init (GStaticPrivate *private_key)
+{
+  private_key->index = 0;
+}
+
+/**
+ * g_static_private_get:
+ * @private_key: a #GStaticPrivate
+ *
+ * Works like g_private_get() only for a #GStaticPrivate.
+ *
+ * This function works even if g_thread_init() has not yet been called.
+ *
+ * Returns: the corresponding pointer
+ */
+gpointer
+g_static_private_get (GStaticPrivate *private_key)
+{
+  GRealThread *self = (GRealThread*) g_thread_self ();
+  GArray *array;
+  gpointer ret = NULL;
+  array = self->private_data;
+
+  if (array && private_key->index != 0 && private_key->index <= array->len)
+    {
+      GStaticPrivateNode *node;
+
+      node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
+
+      /* Deal with the possibility that the GStaticPrivate which used
+       * to have this index got freed and the index got allocated to
+       * a new one. In this case, the data in the node is stale, so
+       * free it and return NULL.
+       */
+      if (G_UNLIKELY (node->owner != private_key))
+        {
+          if (node->destroy)
+            node->destroy (node->data);
+          node->destroy = NULL;
+          node->data = NULL;
+          node->owner = NULL;
+        }
+      ret = node->data;
+    }
+
+  return ret;
+}
+
+/**
+ * g_static_private_set:
+ * @private_key: a #GStaticPrivate
+ * @data: the new pointer
+ * @notify: a function to be called with the pointer whenever the
+ *     current thread ends or sets this pointer again
+ *
+ * Sets the pointer keyed to @private_key for the current thread and
+ * the function @notify to be called with that pointer (%NULL or
+ * non-%NULL), whenever the pointer is set again or whenever the
+ * current thread ends.
+ *
+ * This function works even if g_thread_init() has not yet been called.
+ * If g_thread_init() is called later, the @data keyed to @private_key
+ * will be inherited only by the main thread, i.e. the one that called
+ * g_thread_init().
+ *
+ * <note><para>@notify is used quite differently from @destructor in
+ * g_private_new().</para></note>
+ */
+void
+g_static_private_set (GStaticPrivate *private_key,
+                      gpointer        data,
+                      GDestroyNotify  notify)
+{
+  GRealThread *self = (GRealThread*) g_thread_self ();
+  GArray *array;
+  static guint next_index = 0;
+  GStaticPrivateNode *node;
+
+  if (!private_key->index)
+    {
+      G_LOCK (g_thread);
+
+      if (!private_key->index)
+        {
+          if (g_thread_free_indices)
+            {
+              private_key->index = GPOINTER_TO_UINT (g_thread_free_indices->data);
+              g_thread_free_indices = g_slist_delete_link (g_thread_free_indices,
+                                                           g_thread_free_indices);
+            }
+          else
+            private_key->index = ++next_index;
+        }
+
+      G_UNLOCK (g_thread);
+    }
+
+  array = self->private_data;
+  if (!array)
+    {
+      array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
+      self->private_data = array;
+    }
+  if (private_key->index > array->len)
+    g_array_set_size (array, private_key->index);
+
+  node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
+
+  if (node->destroy)
+    node->destroy (node->data);
+
+  node->data = data;
+  node->destroy = notify;
+  node->owner = private_key;
+}
+
+/**
+ * g_static_private_free:
+ * @private_key: a #GStaticPrivate to be freed
+ *
+ * Releases all resources allocated to @private_key.
+ *
+ * You don't have to call this functions for a #GStaticPrivate with an
+ * unbounded lifetime, i.e. objects declared 'static', but if you have
+ * a #GStaticPrivate as a member of a structure and the structure is
+ * freed, you should also free the #GStaticPrivate.
+ */
+void
+g_static_private_free (GStaticPrivate *private_key)
+{
+  guint idx = private_key->index;
+
+  if (!idx)
+    return;
+
+  private_key->index = 0;
+
+  /* Freeing the per-thread data is deferred to either the
+   * thread end or the next g_static_private_get() call for
+   * the same index.
+   */
+  G_LOCK (g_thread);
+  g_thread_free_indices = g_slist_prepend (g_thread_free_indices,
+                                           GUINT_TO_POINTER (idx));
+  G_UNLOCK (g_thread);
+}
+
+void
+g_static_private_cleanup (GRealThread *thread)
+{
+  GArray *array;
+
+  array = thread->private_data;
+  thread->private_data = NULL;
+
+  if (array)
+    {
+      guint i;
+
+      for (i = 0; i < array->len; i++ )
+        {
+          GStaticPrivateNode *node = &g_array_index (array, GStaticPrivateNode, i);
+          if (node->destroy)
+            node->destroy (node->data);
+        }
+      g_array_free (array, TRUE);
+    }
+}
+
+/* {{{1 Epilogue */
 /* vim: set foldmethod=marker: */
diff --git a/glib/deprecated/gthread.h b/glib/deprecated/gthread.h
index 2d0b3ae..1669991 100644
--- a/glib/deprecated/gthread.h
+++ b/glib/deprecated/gthread.h
@@ -114,6 +114,9 @@ GThread* g_thread_create_full  (GThreadFunc            func,
 void g_thread_set_priority     (GThread         *thread,
                                 GThreadPriority  priority);
 
+void     g_thread_foreach      (GFunc         thread_func,
+                                gpointer      user_data);
+
 #ifdef G_OS_WIN32
 typedef GMutex * GStaticMutex;
 #define G_STATIC_MUTEX_INIT NULL
@@ -179,9 +182,22 @@ gboolean  g_static_rw_lock_writer_trylock (GStaticRWLock* lock);
 void      g_static_rw_lock_writer_unlock  (GStaticRWLock* lock);
 void      g_static_rw_lock_free           (GStaticRWLock* lock);
 
-
 GPrivate *      g_private_new             (GDestroyNotify  notify);
 
+struct _GStaticPrivate
+{
+  /*< private >*/
+  guint index;
+};
+
+#define G_STATIC_PRIVATE_INIT { 0 }
+void     g_static_private_init           (GStaticPrivate   *private_key);
+gpointer g_static_private_get            (GStaticPrivate   *private_key);
+void     g_static_private_set            (GStaticPrivate   *private_key,
+                                          gpointer          data,
+                                          GDestroyNotify    notify);
+void     g_static_private_free           (GStaticPrivate   *private_key);
+
 G_END_DECLS
 
 #endif /* __G_DEPRECATED_THREAD_H__ */
diff --git a/glib/gthread.c b/glib/gthread.c
index a753883..fcac82a 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -42,7 +42,6 @@
 
 #include "gthread.h"
 #include "gthreadprivate.h"
-#include "deprecated/gthread.h"
 
 #include <string.h>
 
@@ -57,9 +56,7 @@
 #include <windows.h>
 #endif /* G_OS_WIN32 */
 
-#include "garray.h"
 #include "gslice.h"
-#include "gslist.h"
 #include "gtestutils.h"
 
 /**
@@ -576,20 +573,6 @@ g_thread_error_quark (void)
   return g_quark_from_static_string ("g_thread_error");
 }
 
-/* Miscellaneous Structures {{{1 ------------------------------------------ */
-
-typedef struct _GRealThread GRealThread;
-struct  _GRealThread
-{
-  GThread thread;
-  GArray *private_data;
-  GRealThread *next;
-  const gchar *name;
-  gboolean enumerable;
-  gpointer retval;
-  GSystemThread system_thread;
-};
-
 /* Local Data {{{1 -------------------------------------------------------- */
 
 gboolean         g_threads_got_initialized = FALSE;
@@ -601,11 +584,8 @@ static GSList   *g_once_init_list = NULL;
 
 static void g_thread_cleanup (gpointer data);
 static GPrivate     g_thread_specific_private = G_PRIVATE_INIT (g_thread_cleanup);
-static GRealThread *g_thread_all_threads = NULL;
-static GSList      *g_thread_free_indices = NULL;
 
-/* Protects g_thread_all_threads and g_thread_free_indices */
-G_LOCK_DEFINE_STATIC (g_thread);
+G_LOCK_DEFINE_STATIC (g_thread_new);
 
 /* Initialisation {{{1 ---------------------------------------------------- */
 
@@ -859,219 +839,6 @@ g_once_init_leave (volatile gsize *value_location,
   g_mutex_unlock (&g_once_mutex);
 }
 
-/* GStaticPrivate {{{1 ---------------------------------------------------- */
-
-typedef struct _GStaticPrivateNode GStaticPrivateNode;
-struct _GStaticPrivateNode
-{
-  gpointer        data;
-  GDestroyNotify  destroy;
-  GStaticPrivate *owner;
-};
-
-/**
- * GStaticPrivate:
- *
- * A #GStaticPrivate works almost like a #GPrivate, but it has one
- * significant advantage. It doesn't need to be created at run-time
- * like a #GPrivate, but can be defined at compile-time. This is
- * similar to the difference between #GMutex and #GStaticMutex. Now
- * look at our <function>give_me_next_number()</function> example with
- * #GStaticPrivate:
- *
- * <example>
- *  <title>Using GStaticPrivate for per-thread data</title>
- *  <programlisting>
- *   int
- *   give_me_next_number (<!-- -->)
- *   {
- *     static GStaticPrivate current_number_key = G_STATIC_PRIVATE_INIT;
- *     int *current_number = g_static_private_get (&amp;current_number_key);
- *
- *     if (!current_number)
- *       {
- *         current_number = g_new (int,1);
- *         *current_number = 0;
- *         g_static_private_set (&amp;current_number_key, current_number, g_free);
- *       }
- *
- *     *current_number = calc_next_number (*current_number);
- *
- *     return *current_number;
- *   }
- *  </programlisting>
- * </example>
- */
-
-/**
- * G_STATIC_PRIVATE_INIT:
- *
- * Every #GStaticPrivate must be initialized with this macro, before it
- * can be used.
- *
- * |[
- *   GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
- * ]|
- */
-
-/**
- * g_static_private_init:
- * @private_key: a #GStaticPrivate to be initialized
- *
- * Initializes @private_key. Alternatively you can initialize it with
- * #G_STATIC_PRIVATE_INIT.
- */
-void
-g_static_private_init (GStaticPrivate *private_key)
-{
-  private_key->index = 0;
-}
-
-/**
- * g_static_private_get:
- * @private_key: a #GStaticPrivate
- *
- * Works like g_private_get() only for a #GStaticPrivate.
- *
- * This function works even if g_thread_init() has not yet been called.
- *
- * Returns: the corresponding pointer
- */
-gpointer
-g_static_private_get (GStaticPrivate *private_key)
-{
-  GRealThread *self = (GRealThread*) g_thread_self ();
-  GArray *array;
-  gpointer ret = NULL;
-
-  array = self->private_data;
-
-  if (array && private_key->index != 0 && private_key->index <= array->len)
-    {
-      GStaticPrivateNode *node;
-
-      node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
-
-      /* Deal with the possibility that the GStaticPrivate which used
-       * to have this index got freed and the index got allocated to
-       * a new one. In this case, the data in the node is stale, so
-       * free it and return NULL.
-       */
-      if (G_UNLIKELY (node->owner != private_key))
-        {
-          if (node->destroy)
-            node->destroy (node->data);
-          node->destroy = NULL;
-          node->data = NULL;
-          node->owner = NULL;
-        }
-
-      ret = node->data;
-    }
-
-  return ret;
-}
-
-/**
- * g_static_private_set:
- * @private_key: a #GStaticPrivate
- * @data: the new pointer
- * @notify: a function to be called with the pointer whenever the
- *     current thread ends or sets this pointer again
- *
- * Sets the pointer keyed to @private_key for the current thread and
- * the function @notify to be called with that pointer (%NULL or
- * non-%NULL), whenever the pointer is set again or whenever the
- * current thread ends.
- *
- * This function works even if g_thread_init() has not yet been called.
- * If g_thread_init() is called later, the @data keyed to @private_key
- * will be inherited only by the main thread, i.e. the one that called
- * g_thread_init().
- *
- * <note><para>@notify is used quite differently from @destructor in
- * g_private_new().</para></note>
- */
-void
-g_static_private_set (GStaticPrivate *private_key,
-                      gpointer        data,
-                      GDestroyNotify  notify)
-{
-  GRealThread *self = (GRealThread*) g_thread_self ();
-  GArray *array;
-  static guint next_index = 0;
-  GStaticPrivateNode *node;
-
-  if (!private_key->index)
-    {
-      G_LOCK (g_thread);
-
-      if (!private_key->index)
-        {
-          if (g_thread_free_indices)
-            {
-              private_key->index = GPOINTER_TO_UINT (g_thread_free_indices->data);
-              g_thread_free_indices = g_slist_delete_link (g_thread_free_indices,
-                                                           g_thread_free_indices);
-            }
-          else
-            private_key->index = ++next_index;
-        }
-
-      G_UNLOCK (g_thread);
-    }
-
-  array = self->private_data;
-  if (!array)
-    {
-      array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
-      self->private_data = array;
-    }
-
-  if (private_key->index > array->len)
-    g_array_set_size (array, private_key->index);
-
-  node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
-
-  if (node->destroy)
-    node->destroy (node->data);
-
-  node->data = data;
-  node->destroy = notify;
-  node->owner = private_key;
-}
-
-/**
- * g_static_private_free:
- * @private_key: a #GStaticPrivate to be freed
- *
- * Releases all resources allocated to @private_key.
- *
- * You don't have to call this functions for a #GStaticPrivate with an
- * unbounded lifetime, i.e. objects declared 'static', but if you have
- * a #GStaticPrivate as a member of a structure and the structure is
- * freed, you should also free the #GStaticPrivate.
- */
-void
-g_static_private_free (GStaticPrivate *private_key)
-{
-  guint idx = private_key->index;
-
-  if (!idx)
-    return;
-
-  private_key->index = 0;
-
-  /* Freeing the per-thread data is deferred to either the
-   * thread end or the next g_static_private_get() call for
-   * the same index.
-   */
-  G_LOCK (g_thread);
-  g_thread_free_indices = g_slist_prepend (g_thread_free_indices,
-                                           GUINT_TO_POINTER (idx));
-  G_UNLOCK (g_thread);
-}
-
 /* GThread {{{1 -------------------------------------------------------- */
 
 static void
@@ -1080,23 +847,8 @@ g_thread_cleanup (gpointer data)
   if (data)
     {
       GRealThread* thread = data;
-      GArray *array;
-
-      array = thread->private_data;
-      thread->private_data = NULL;
 
-      if (array)
-        {
-          guint i;
-
-          for (i = 0; i < array->len; i++ )
-            {
-              GStaticPrivateNode *node = &g_array_index (array, GStaticPrivateNode, i);
-              if (node->destroy)
-                node->destroy (node->data);
-            }
-          g_array_free (array, TRUE);
-        }
+      g_static_private_cleanup (thread);
 
       /* We only free the thread structure if it isn't joinable.
        * If it is, the structure is freed in g_thread_join()
@@ -1104,23 +856,8 @@ g_thread_cleanup (gpointer data)
       if (!thread->thread.joinable)
         {
           if (thread->enumerable)
-            {
-              GRealThread *t, *p;
-
-              G_LOCK (g_thread);
-              for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
-                {
-                  if (t == thread)
-                    {
-                      if (p)
-                        p->next = t->next;
-                      else
-                        g_thread_all_threads = t->next;
-                      break;
-                    }
-                }
-              G_UNLOCK (g_thread);
-            }
+            g_enumerable_thread_remove (thread);
+
           /* Just to make sure, this isn't used any more */
           g_system_thread_assign (thread->system_thread, zero_thread);
           g_free (thread);
@@ -1144,8 +881,8 @@ g_thread_create_proxy (gpointer data)
   /* The lock makes sure that thread->system_thread is written,
    * before thread->thread.func is called. See g_thread_create().
    */
-  G_LOCK (g_thread);
-  G_UNLOCK (g_thread);
+  G_LOCK (g_thread_new);
+  G_UNLOCK (g_thread_new);
 
   thread->retval = thread->thread.func (thread->thread.data);
 
@@ -1260,16 +997,13 @@ g_thread_new_internal (const gchar  *name,
   result->private_data = NULL;
   result->enumerable = enumerable;
   result->name = name;
-  G_LOCK (g_thread);
+  G_LOCK (g_thread_new);
   g_system_thread_create (g_thread_create_proxy, result,
                           stack_size, joinable,
                           &result->system_thread, &local_error);
   if (enumerable && !local_error)
-    {
-      result->next = g_thread_all_threads;
-      g_thread_all_threads = result;
-    }
-  G_UNLOCK (g_thread);
+    g_enumerable_thread_add (result);
+  G_UNLOCK (g_thread_new);
 
   if (local_error)
     {
@@ -1328,7 +1062,6 @@ gpointer
 g_thread_join (GThread *thread)
 {
   GRealThread *real = (GRealThread*) thread;
-  GRealThread *p, *t;
   gpointer retval;
 
   g_return_val_if_fail (thread, NULL);
@@ -1340,21 +1073,8 @@ g_thread_join (GThread *thread)
   retval = real->retval;
 
   if (real->enumerable)
-    {
-      G_LOCK (g_thread);
-      for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
-        {
-          if (t == real)
-            {
-              if (p)
-                p->next = t->next;
-              else
-                g_thread_all_threads = t->next;
-              break;
-            }
-        }
-      G_UNLOCK (g_thread);
-    }
+    g_enumerable_thread_remove (real);
+
   /* Just to make sure, this isn't used any more */
   thread->joinable = 0;
   g_system_thread_assign (real->system_thread, zero_thread);
@@ -1402,52 +1122,6 @@ g_thread_self (void)
   return (GThread*)thread;
 }
 
-/**
- * g_thread_foreach:
- * @thread_func: function to call for all #GThread structures
- * @user_data: second argument to @thread_func
- *
- * Call @thread_func on all existing #GThread structures.
- * Note that threads may decide to exit while @thread_func is
- * running, so without intimate knowledge about the lifetime of
- * foreign threads, @thread_func shouldn't access the GThread*
- * pointer passed in as first argument. However, @thread_func will
- * not be called for threads which are known to have exited already.
- *
- * Due to thread lifetime checks, this function has an execution complexity
- * which is quadratic in the number of existing threads.
- *
- * Since: 2.10
- */
-void
-g_thread_foreach (GFunc    thread_func,
-                  gpointer user_data)
-{
-  GSList *slist = NULL;
-  GRealThread *thread;
-  g_return_if_fail (thread_func != NULL);
-  /* snapshot the list of threads for iteration */
-  G_LOCK (g_thread);
-  for (thread = g_thread_all_threads; thread; thread = thread->next)
-    slist = g_slist_prepend (slist, thread);
-  G_UNLOCK (g_thread);
-  /* walk the list, skipping non-existent threads */
-  while (slist)
-    {
-      GSList *node = slist;
-      slist = node->next;
-      /* check whether the current thread still exists */
-      G_LOCK (g_thread);
-      for (thread = g_thread_all_threads; thread; thread = thread->next)
-        if (thread == node->data)
-          break;
-      G_UNLOCK (g_thread);
-      if (thread)
-        thread_func (thread, user_data);
-      g_slist_free_1 (node);
-    }
-}
-
 /* GMutex {{{1 ------------------------------------------------------ */
 
 /**
diff --git a/glib/gthread.h b/glib/gthread.h
index 18f9740..93b78dd 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -152,22 +152,6 @@ void     g_thread_exit                   (gpointer      retval);
 gpointer g_thread_join                   (GThread      *thread);
 void     g_thread_yield                  (void);
 
-void     g_thread_foreach                (GFunc         thread_func,
-                                          gpointer      user_data);
-
-struct _GStaticPrivate
-{
-  /*< private >*/
-  guint index;
-};
-#define G_STATIC_PRIVATE_INIT { 0 }
-void     g_static_private_init           (GStaticPrivate   *private_key);
-gpointer g_static_private_get            (GStaticPrivate   *private_key);
-void     g_static_private_set            (GStaticPrivate   *private_key,
-					  gpointer          data,
-					  GDestroyNotify    notify);
-void     g_static_private_free           (GStaticPrivate   *private_key);
-
 typedef enum
 {
   G_ONCE_STATUS_NOTCALLED,
diff --git a/glib/gthreadprivate.h b/glib/gthreadprivate.h
index 1a95668..d7dab76 100644
--- a/glib/gthreadprivate.h
+++ b/glib/gthreadprivate.h
@@ -23,6 +23,10 @@
 #ifndef __G_THREADPRIVATE_H__
 #define __G_THREADPRIVATE_H__
 
+#include "deprecated/gthread.h"
+#include "garray.h"
+#include "gslist.h"
+
 G_BEGIN_DECLS
 
 /* System thread identifier comparison and assignment */
@@ -56,9 +60,25 @@ G_GNUC_INTERNAL GThread *g_thread_new_internal (const gchar  *name,
                                                 gboolean      enumerable,
                                                 GError      **error);
 
+typedef struct _GRealThread GRealThread;
+struct  _GRealThread
+{
+  GThread thread;
+  GArray *private_data;
+  GRealThread *next;
+  const gchar *name;
+  gboolean enumerable;
+  gpointer retval;
+  GSystemThread system_thread;
+};
+
 G_GNUC_INTERNAL GSystemThread zero_thread;
 G_GNUC_INTERNAL GMutex g_once_mutex;
 
+G_GNUC_INTERNAL void g_static_private_cleanup   (GRealThread *thread);
+G_GNUC_INTERNAL void g_enumerable_thread_add    (GRealThread *thread);
+G_GNUC_INTERNAL void g_enumerable_thread_remove (GRealThread *thread);
+
 /* Is called from gthread/gthread-impl.c */
 void g_thread_init_glib (void);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]