drop g_thread_new_full()
[platform/upstream/glib.git] / glib / deprecated / gthread-deprecated.c
index 8bed9fe..c6aa3ef 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "config.h"
 
+/* we know we are deprecated here, no need for warnings */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
 #include "gmessages.h"
 #include "gslice.h"
 #include "gmain.h"
 #include "gthreadprivate.h"
 #include "deprecated/gthread.h"
 
+#include "gutils.h"
+
 /* {{{1 Documentation */
 
 /**
+ * SECTION:threads-deprecated
+ * @title: Deprecated thread API
+ * @short_description: old thread APIs (for reference only)
+ * @see_also: #GThread
+ *
+ * These APIs are deprecated.  You should not use them in new code.
+ * This section remains only to assist with understanding code that was
+ * written to use these APIs at some point in the past.
+ **/
+
+/**
  * GThreadPriority:
  * @G_THREAD_PRIORITY_LOW: a priority lower than normal
  * @G_THREAD_PRIORITY_NORMAL: the default priority
  * to initialize the thread system.
  */
 
+/**
+ * G_THREADS_IMPL_POSIX:
+ *
+ * This macro is defined if POSIX style threads are used.
+ *
+ * Deprecated:2.32:POSIX threads are in use on all non-Windows systems.
+ *                 Use G_OS_WIN32 to detect Windows.
+ */
+
+/**
+ * G_THREADS_IMPL_WIN32:
+ *
+ * This macro is defined if Windows style threads are used.
+ *
+ * Deprecated:2.32:Use G_OS_WIN32 to detect Windows.
+ */
+
+
 /* {{{1 Exported Variables */
 
-gboolean g_thread_use_default_impl = TRUE;
+/* Set this FALSE to have previously-compiled GStaticMutex code use the
+ * slow path (ie: call into us) to avoid compatibility problems.
+ */
+gboolean g_thread_use_default_impl = FALSE;
 
 GThreadFunctions g_thread_functions_for_glib_use =
 {
@@ -111,8 +148,6 @@ guint64 (*g_thread_gettime) (void) = gettime;
 
 /* Initialisation {{{1 ---------------------------------------------------- */
 gboolean         g_threads_got_initialized = TRUE;
-GSystemThread    zero_thread; /* This is initialized to all zero */
-
 
 /**
  * g_thread_init:
@@ -160,10 +195,11 @@ void g_thread_init_glib (void) { }
 
 /* Internal variables {{{1 */
 
-static GRealThread *g_thread_all_threads = NULL;
+static GSList      *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_static_mutex);
 G_LOCK_DEFINE_STATIC (g_thread);
 
 /* Misc. GThread functions {{{1 */
@@ -184,66 +220,6 @@ g_thread_set_priority (GThread         *thread,
 }
 
 /**
- * g_thread_create:
- * @func: a function to execute in the new thread
- * @data: an argument to supply to the new thread
- * @joinable: should this thread be joinable?
- * @error: return location for error, or %NULL
- *
- * This function creates a new thread.
- *
- * If @joinable is %TRUE, you can wait for this threads termination
- * calling g_thread_join(). Otherwise the thread will just disappear
- * when it terminates.
- *
- * The new thread executes the function @func with the argument @data.
- * If the thread was created successfully, it is returned.
- *
- * @error can be %NULL to ignore errors, or non-%NULL to report errors.
- * The error is set, if and only if the function returns %NULL.
- *
- * Returns: the new #GThread on success
- *
- * Deprecated:2.32: Use g_thread_new() instead
- */
-GThread *
-g_thread_create (GThreadFunc   func,
-                 gpointer      data,
-                 gboolean      joinable,
-                 GError      **error)
-{
-  return g_thread_new_internal (NULL, func, data, joinable, 0, TRUE, error);
-}
-
-/**
- * g_thread_create_full:
- * @func: a function to execute in the new thread.
- * @data: an argument to supply to the new thread.
- * @stack_size: a stack size for the new thread.
- * @joinable: should this thread be joinable?
- * @bound: ignored
- * @priority: ignored
- * @error: return location for error.
- * @Returns: the new #GThread on success.
- *
- * This function creates a new thread.
- *
- * Deprecated:2.32: The @bound and @priority arguments are now ignored.
- * Use g_thread_new() or g_thread_new_full() instead.
- */
-GThread *
-g_thread_create_full (GThreadFunc       func,
-                      gpointer          data,
-                      gulong            stack_size,
-                      gboolean          joinable,
-                      gboolean          bound,
-                      GThreadPriority   priority,
-                      GError          **error)
-{
-  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
@@ -275,8 +251,7 @@ g_thread_foreach (GFunc    thread_func,
   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);
+  slist = g_slist_copy (g_thread_all_threads);
   G_UNLOCK (g_thread);
   /* walk the list, skipping non-existent threads */
   while (slist)
@@ -285,9 +260,10 @@ g_thread_foreach (GFunc    thread_func,
       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;
+      if (g_slist_find (g_thread_all_threads, node->data))
+        thread = node->data;
+      else
+        thread = NULL;
       G_UNLOCK (g_thread);
       if (thread)
         thread_func (thread, user_data);
@@ -295,33 +271,108 @@ g_thread_foreach (GFunc    thread_func,
     }
 }
 
-void
+static void
+g_enumerable_thread_remove (gpointer data)
+{
+  GRealThread *thread = data;
+
+  G_LOCK (g_thread);
+  g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
+  G_UNLOCK (g_thread);
+}
+
+GPrivate enumerable_thread_private = G_PRIVATE_INIT (g_enumerable_thread_remove);
+
+static void
 g_enumerable_thread_add (GRealThread *thread)
 {
   G_LOCK (g_thread);
-  thread->next = g_thread_all_threads;
-  g_thread_all_threads = thread;
+  g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
   G_UNLOCK (g_thread);
+
+  g_private_set (&enumerable_thread_private, thread);
 }
 
-void
-g_enumerable_thread_remove (GRealThread *thread)
+static gpointer
+g_deprecated_thread_proxy (gpointer data)
 {
-  GRealThread *t, *p;
+  GRealThread *real = data;
 
-  G_LOCK (g_thread);
-  for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+  g_enumerable_thread_add (real);
+
+  return g_thread_proxy (data);
+}
+
+/**
+ * g_thread_create:
+ * @func: a function to execute in the new thread
+ * @data: an argument to supply to the new thread
+ * @joinable: should this thread be joinable?
+ * @error: return location for error, or %NULL
+ *
+ * This function creates a new thread.
+ *
+ * The new thread executes the function @func with the argument @data.
+ * If the thread was created successfully, it is returned.
+ *
+ * @error can be %NULL to ignore errors, or non-%NULL to report errors.
+ * The error is set, if and only if the function returns %NULL.
+ *
+ * This function returns a reference to the created thread only if
+ * @joinable is %TRUE.  In that case, you must free this reference by
+ * calling g_thread_unref() or g_thread_join().  If @joinable is %FALSE
+ * then you should probably not touch the return value.
+ *
+ * Returns: the new #GThread on success
+ *
+ * Deprecated:2.32: Use g_thread_new() instead
+ */
+GThread *
+g_thread_create (GThreadFunc   func,
+                 gpointer      data,
+                 gboolean      joinable,
+                 GError      **error)
+{
+  return g_thread_create_full (func, data, 0, joinable, 0, 0, error);
+}
+
+/**
+ * g_thread_create_full:
+ * @func: a function to execute in the new thread.
+ * @data: an argument to supply to the new thread.
+ * @stack_size: a stack size for the new thread.
+ * @joinable: should this thread be joinable?
+ * @bound: ignored
+ * @priority: ignored
+ * @error: return location for error.
+ * @Returns: the new #GThread on success.
+ *
+ * This function creates a new thread.
+ *
+ * Deprecated:2.32: The @bound and @priority arguments are now ignored.
+ * Use g_thread_new().
+ */
+GThread *
+g_thread_create_full (GThreadFunc       func,
+                      gpointer          data,
+                      gulong            stack_size,
+                      gboolean          joinable,
+                      gboolean          bound,
+                      GThreadPriority   priority,
+                      GError          **error)
+{
+  GThread *thread;
+
+  thread = g_thread_new_internal (NULL, g_deprecated_thread_proxy,
+                                  func, data, stack_size, error);
+
+  if (!joinable)
     {
-      if (t == thread)
-        {
-          if (p)
-            p->next = t->next;
-          else
-            g_thread_all_threads = t->next;
-          break;
-        }
+      thread->joinable = FALSE;
+      g_thread_unref (thread);
     }
-  G_UNLOCK (g_thread);
+
+  return thread;
 }
 
 /* GOnce {{{1 ------------------------------------------------------------- */
@@ -453,27 +504,27 @@ g_static_mutex_init (GStaticMutex *mutex)
  * Deprecated: 2.32: Just use a #GMutex
  */
 GMutex *
-g_static_mutex_get_mutex_impl (GMutex** mutex)
+g_static_mutex_get_mutex_impl (GStaticMutex* mutex)
 {
   GMutex *result;
 
   if (!g_thread_supported ())
     return NULL;
 
-  result = g_atomic_pointer_get (mutex);
+  result = g_atomic_pointer_get (&mutex->mutex);
 
   if (!result)
     {
-      g_mutex_lock (&g_once_mutex);
+      G_LOCK (g_static_mutex);
 
-      result = *mutex;
+      result = mutex->mutex;
       if (!result)
         {
           result = g_mutex_new ();
-          g_atomic_pointer_set (mutex, result);
+          g_atomic_pointer_set (&mutex->mutex, result);
         }
 
-      g_mutex_unlock (&g_once_mutex);
+      G_UNLOCK (g_static_mutex);
     }
 
   return result;
@@ -608,6 +659,34 @@ g_static_rec_mutex_init (GStaticRecMutex *mutex)
   *mutex = init_mutex;
 }
 
+static GRecMutex *
+g_static_rec_mutex_get_rec_mutex_impl (GStaticRecMutex* mutex)
+{
+  GRecMutex *result;
+
+  if (!g_thread_supported ())
+    return NULL;
+
+  result = g_atomic_pointer_get (&mutex->mutex.mutex);
+
+  if (!result)
+    {
+      G_LOCK (g_static_mutex);
+
+      result = (GRecMutex *) mutex->mutex.mutex;
+      if (!result)
+        {
+          result = g_slice_new (GRecMutex);
+          g_rec_mutex_init (result);
+          g_atomic_pointer_set (&mutex->mutex.mutex, result);
+        }
+
+      G_UNLOCK (g_static_mutex);
+    }
+
+  return result;
+}
+
 /**
  * g_static_rec_mutex_lock:
  * @mutex: a #GStaticRecMutex to lock.
@@ -622,23 +701,10 @@ g_static_rec_mutex_init (GStaticRecMutex *mutex)
 void
 g_static_rec_mutex_lock (GStaticRecMutex* mutex)
 {
-  GSystemThread self;
-
-  g_return_if_fail (mutex);
-
-  if (!g_thread_supported ())
-    return;
-
-  g_system_thread_self (&self);
-
-  if (g_system_thread_equal (&self, &mutex->owner))
-    {
-      mutex->depth++;
-      return;
-    }
-  g_static_mutex_lock (&mutex->mutex);
-  g_system_thread_assign (mutex->owner, self);
-  mutex->depth = 1;
+  GRecMutex *rm;
+  rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
+  g_rec_mutex_lock (rm);
+  mutex->depth++;
 }
 
 /**
@@ -657,27 +723,16 @@ g_static_rec_mutex_lock (GStaticRecMutex* mutex)
 gboolean
 g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
 {
-  GSystemThread self;
-
-  g_return_val_if_fail (mutex, FALSE);
+  GRecMutex *rm;
+  rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
 
-  if (!g_thread_supported ())
-    return TRUE;
-
-  g_system_thread_self (&self);
-
-  if (g_system_thread_equal (&self, &mutex->owner))
+  if (g_rec_mutex_trylock (rm))
     {
       mutex->depth++;
       return TRUE;
     }
-
-  if (!g_static_mutex_trylock (&mutex->mutex))
+  else
     return FALSE;
-
-  g_system_thread_assign (mutex->owner, self);
-  mutex->depth = 1;
-  return TRUE;
 }
 
 /**
@@ -695,18 +750,10 @@ g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
 void
 g_static_rec_mutex_unlock (GStaticRecMutex* mutex)
 {
-  g_return_if_fail (mutex);
-
-  if (!g_thread_supported ())
-    return;
-
-  if (mutex->depth > 1)
-    {
-      mutex->depth--;
-      return;
-    }
-  g_system_thread_assign (mutex->owner, zero_thread);
-  g_static_mutex_unlock (&mutex->mutex);
+  GRecMutex *rm;
+  rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
+  mutex->depth--;
+  g_rec_mutex_unlock (rm);
 }
 
 /**
@@ -723,25 +770,14 @@ void
 g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
                               guint            depth)
 {
-  GSystemThread self;
-  g_return_if_fail (mutex);
-
-  if (!g_thread_supported ())
-    return;
-
-  if (depth == 0)
-    return;
+  GRecMutex *rm;
 
-  g_system_thread_self (&self);
-
-  if (g_system_thread_equal (&self, &mutex->owner))
+  rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
+  while (depth--)
     {
-      mutex->depth += depth;
-      return;
+      g_rec_mutex_lock (rm);
+      mutex->depth++;
     }
-  g_static_mutex_lock (&mutex->mutex);
-  g_system_thread_assign (mutex->owner, self);
-  mutex->depth = depth;
 }
 
 /**
@@ -763,18 +799,13 @@ g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
 guint
 g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
 {
-  guint depth;
-
-  g_return_val_if_fail (mutex, 0);
-
-  if (!g_thread_supported ())
-    return 1;
+  GRecMutex *rm;
+  gint depth;
 
+  rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
   depth = mutex->depth;
-
-  g_system_thread_assign (mutex->owner, zero_thread);
-  mutex->depth = 0;
-  g_static_mutex_unlock (&mutex->mutex);
+  while (mutex->depth--)
+    g_rec_mutex_unlock (rm);
 
   return depth;
 }
@@ -797,7 +828,13 @@ g_static_rec_mutex_free (GStaticRecMutex *mutex)
 {
   g_return_if_fail (mutex);
 
-  g_static_mutex_free (&mutex->mutex);
+  if (mutex->mutex.mutex)
+    {
+      GRecMutex *rm = (GRecMutex *) mutex->mutex.mutex;
+
+      g_rec_mutex_clear (rm);
+      g_slice_free (GRecMutex, rm);
+    }
 }
 
 /* GStaticRWLock {{{1 ----------------------------------------------------- */
@@ -1184,6 +1221,24 @@ struct _GStaticPrivateNode
   GStaticPrivate *owner;
 };
 
+static void
+g_static_private_cleanup (gpointer data)
+{
+  GArray *array = data;
+  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);
+}
+
+GPrivate static_private_private = G_PRIVATE_INIT (g_static_private_cleanup);
+
 /**
  * GStaticPrivate:
  *
@@ -1255,10 +1310,10 @@ g_static_private_init (GStaticPrivate *private_key)
 gpointer
 g_static_private_get (GStaticPrivate *private_key)
 {
-  GRealThread *self = (GRealThread*) g_thread_self ();
   GArray *array;
   gpointer ret = NULL;
-  array = self->private_data;
+
+  array = g_private_get (&static_private_private);
 
   if (array && private_key->index != 0 && private_key->index <= array->len)
     {
@@ -1310,7 +1365,6 @@ 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;
@@ -1334,11 +1388,11 @@ g_static_private_set (GStaticPrivate *private_key,
       G_UNLOCK (g_thread);
     }
 
-  array = self->private_data;
+  array = g_private_get (&static_private_private);
   if (!array)
     {
       array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
-      self->private_data = array;
+      g_private_set (&static_private_private, array);
     }
   if (private_key->index > array->len)
     g_array_set_size (array, private_key->index);
@@ -1384,26 +1438,88 @@ g_static_private_free (GStaticPrivate *private_key)
   G_UNLOCK (g_thread);
 }
 
+/* GMutex {{{1 ------------------------------------------------------ */
+
+/**
+ * g_mutex_new:
+ *
+ * Allocates and initializes a new #GMutex.
+ *
+ * Returns: a newly allocated #GMutex. Use g_mutex_free() to free
+ *
+ * Deprecated:3.32:GMutex can now be statically allocated, or embedded
+ * in structures and initialised with g_mutex_init().
+ */
+GMutex *
+g_mutex_new (void)
+{
+  GMutex *mutex;
+
+  mutex = g_slice_new (GMutex);
+  g_mutex_init (mutex);
+
+  return mutex;
+}
+
+/**
+ * g_mutex_free:
+ * @mutex: a #GMutex
+ *
+ * Destroys a @mutex that has been created with g_mutex_new().
+ *
+ * Calling g_mutex_free() on a locked mutex may result
+ * in undefined behaviour.
+ *
+ * Deprecated:3.32:GMutex can now be statically allocated, or embedded
+ * in structures and initialised with g_mutex_init().
+ */
 void
-g_static_private_cleanup (GRealThread *thread)
+g_mutex_free (GMutex *mutex)
 {
-  GArray *array;
+  g_mutex_clear (mutex);
+  g_slice_free (GMutex, mutex);
+}
 
-  array = thread->private_data;
-  thread->private_data = NULL;
+/* GCond {{{1 ------------------------------------------------------ */
 
-  if (array)
-    {
-      guint i;
+/**
+ * g_cond_new:
+ *
+ * Allocates and initializes a new #GCond.
+ *
+ * Returns: a newly allocated #GCond. Free with g_cond_free()
+ *
+ * Deprecated:3.32:GCond can now be statically allocated, or embedded
+ * in structures and initialised with g_cond_init().
+ */
+GCond *
+g_cond_new (void)
+{
+  GCond *cond;
 
-      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);
-    }
+  cond = g_slice_new (GCond);
+  g_cond_init (cond);
+
+  return cond;
+}
+
+/**
+ * g_cond_free:
+ * @cond: a #GCond
+ *
+ * Destroys a #GCond that has been created with g_cond_new().
+ *
+ * Calling g_cond_free() for a #GCond on which threads are
+ * blocking leads to undefined behaviour.
+ *
+ * Deprecated:3.32:GCond can now be statically allocated, or embedded
+ * in structures and initialised with g_cond_init().
+ */
+void
+g_cond_free (GCond *cond)
+{
+  g_cond_clear (cond);
+  g_slice_free (GCond, cond);
 }
 
 /* {{{1 Epilogue */