Merge g_thread_functions_for_glib_use
[platform/upstream/glib.git] / glib / gthread-posix.c
index 10ef8ed..01bd092 100644 (file)
@@ -60,6 +60,37 @@ g_thread_abort (gint         status,
 }
 
 /* {{{1 GMutex */
+
+/**
+ * g_mutex_init:
+ * @mutex: an uninitialized #GMutex
+ *
+ * Initializes a #GMutex so that it can be used.
+ *
+ * This function is useful to initialize a mutex that has been
+ * allocated on the stack, or as part of a larger structure.
+ * It is not necessary to initialize a mutex that has been
+ * created with g_mutex_new(). Also see #G_MUTEX_INITIALIZER
+ * for an alternative way to initialize statically allocated mutexes.
+ *
+ * |[
+ *   typedef struct {
+ *     GMutex m;
+ *     /* ... */
+ *   } Blob;
+ *
+ * Blob *b;
+ *
+ * b = g_new (Blob, 1);
+ * g_mutex_init (&b->m);
+ * /* ... */
+ * ]|
+ *
+ * To undo the effect of g_mutex_init() when a mutex is no longer
+ * needed, use g_mutex_clear().
+ *
+ * Since: 2.32
+ */
 void
 g_mutex_init (GMutex *mutex)
 {
@@ -69,6 +100,17 @@ g_mutex_init (GMutex *mutex)
     g_thread_abort (status, "pthread_mutex_init");
 }
 
+/**
+ * g_mutex_clear:
+ * @mutex: an initialized #GMutex
+ *
+ * Frees the resources allocated to a mutex with g_mutex_init().
+ *
+ * #GMutexes that have have been created with g_mutex_new() should
+ * be freed with g_mutex_free() instead.
+ *
+ * Sine: 2.32
+ */
 void
 g_mutex_clear (GMutex *mutex)
 {
@@ -78,6 +120,22 @@ g_mutex_clear (GMutex *mutex)
     g_thread_abort (status, "pthread_mutex_destroy");
 }
 
+/**
+ * g_mutex_lock:
+ * @mutex: a #GMutex
+ *
+ * Locks @mutex. If @mutex is already locked by another thread, the
+ * current thread will block until @mutex is unlocked by the other
+ * thread.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ *
+ * <note>#GMutex is neither guaranteed to be recursive nor to be
+ * non-recursive, i.e. a thread could deadlock while calling
+ * g_mutex_lock(), if it already has locked @mutex. Use
+ * #GStaticRecMutex, if you need recursive mutexes.</note>
+ */
 void
 g_mutex_lock (GMutex *mutex)
 {
@@ -87,6 +145,16 @@ g_mutex_lock (GMutex *mutex)
     g_thread_abort (status, "pthread_mutex_lock");
 }
 
+/**
+ * g_mutex_unlock:
+ * @mutex: a #GMutex
+ *
+ * Unlocks @mutex. If another thread is blocked in a g_mutex_lock()
+ * call for @mutex, it will be woken and can lock @mutex itself.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
 void
 g_mutex_unlock (GMutex *mutex)
 {
@@ -96,6 +164,25 @@ g_mutex_unlock (GMutex *mutex)
     g_thread_abort (status, "pthread_mutex_lock");
 }
 
+/**
+ * g_mutex_trylock:
+ * @mutex: a #GMutex
+ *
+ * Tries to lock @mutex. If @mutex is already locked by another thread,
+ * it immediately returns %FALSE. Otherwise it locks @mutex and returns
+ * %TRUE.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return %TRUE.
+ *
+ * <note>#GMutex is neither guaranteed to be recursive nor to be
+ * non-recursive, i.e. the return value of g_mutex_trylock() could be
+ * both %FALSE or %TRUE, if the current thread already has locked
+ * @mutex. Use #GStaticRecMutex, if you need recursive
+ * mutexes.</note>
+
+ * Returns: %TRUE, if @mutex could be locked
+ */
 gboolean
 g_mutex_trylock (GMutex *mutex)
 {
@@ -112,6 +199,21 @@ g_mutex_trylock (GMutex *mutex)
 
 /* {{{1 GCond */
 
+/**
+ * g_cond_init:
+ * @cond: an uninitialized #GCond
+ *
+ * Initialized a #GCond so that it can be used.
+ *
+ * This function is useful to initialize a #GCond that has been
+ * allocated on the stack, or as part of a larger structure.
+ * It is not necessary to initialize a #GCond that has been
+ * created with g_cond_new(). Also see #G_COND_INITIALIZER
+ * for an alternative way to initialize statically allocated
+ * #GConds.
+ *
+ * Since: 2.32
+ */
 void
 g_cond_init (GCond *cond)
 {
@@ -121,6 +223,17 @@ g_cond_init (GCond *cond)
     g_thread_abort (status, "pthread_cond_init");
 }
 
+/**
+ * g_cond_clear:
+ * @cond: an initialized #GCond
+ *
+ * Frees the resources allocated ot a #GCond with g_cond_init().
+ *
+ * #GConds that have been created with g_cond_new() should
+ * be freed with g_cond_free() instead.
+ *
+ * Since: 2.32
+ */
 void
 g_cond_clear (GCond *cond)
 {
@@ -130,6 +243,18 @@ g_cond_clear (GCond *cond)
     g_thread_abort (status, "pthread_cond_destroy");
 }
 
+/**
+ * g_cond_wait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ *
+ * Waits until this thread is woken up on @cond.
+ * The @mutex is unlocked before falling asleep
+ * and locked again before resuming.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return.
+ */
 void
 g_cond_wait (GCond  *cond,
              GMutex *mutex)
@@ -140,6 +265,17 @@ g_cond_wait (GCond  *cond,
     g_thread_abort (status, "pthread_cond_wait");
 }
 
+/**
+ * g_cond_signal:
+ * @cond: a #GCond
+ *
+ * If threads are waiting for @cond, exactly one of them is woken up.
+ * It is good practice to hold the same lock as the waiting thread
+ * while calling this function, though not required.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
 void
 g_cond_signal (GCond *cond)
 {
@@ -149,6 +285,17 @@ g_cond_signal (GCond *cond)
     g_thread_abort (status, "pthread_cond_signal");
 }
 
+/**
+ * g_cond_broadcast:
+ * @cond: a #GCond
+ *
+ * If threads are waiting for @cond, all of them are woken up.
+ * It is good practice to lock the same mutex as the waiting threads
+ * while calling this function, though not required.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
 void
 g_cond_broadcast (GCond *cond)
 {
@@ -158,6 +305,26 @@ g_cond_broadcast (GCond *cond)
     g_thread_abort (status, "pthread_cond_broadcast");
 }
 
+/**
+ * g_cond_timed_wait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ * @abs_time: a #GTimeVal, determining the final time
+ *
+ * Waits until this thread is woken up on @cond, but not longer than
+ * until the time specified by @abs_time. The @mutex is unlocked before
+ * falling asleep and locked again before resuming.
+ *
+ * If @abs_time is %NULL, g_cond_timed_wait() acts like g_cond_wait().
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return %TRUE.
+ *
+ * To easily calculate @abs_time a combination of g_get_current_time()
+ * and g_time_val_add() can be used.
+ *
+ * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
+ */
 gboolean
 g_cond_timed_wait (GCond    *cond,
                    GMutex   *mutex,
@@ -184,6 +351,20 @@ g_cond_timed_wait (GCond    *cond,
   return FALSE;
 }
 
+/**
+ * g_cond_timedwait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ * @abs_time: the final time, in microseconds
+ *
+ * A variant of g_cond_timed_wait() that takes @abs_time
+ * as a #gint64 instead of a #GTimeVal.
+ * See g_cond_timed_wait() for details.
+ *
+ * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
+ *
+ * Since: 2.32
+ */
 gboolean
 g_cond_timedwait (GCond  *cond,
                   GMutex *mutex,
@@ -206,19 +387,6 @@ g_cond_timedwait (GCond  *cond,
 
 /* {{{1 GPrivate */
 
-GPrivate *
-g_private_new (GDestroyNotify notify)
-{
-  GPrivate *key;
-
-  key = malloc (sizeof (GPrivate));
-  if G_UNLIKELY (key == NULL)
-    g_thread_abort (errno, "malloc");
-  g_private_init (key, notify);
-
-  return key;
-}
-
 void
 g_private_init (GPrivate       *key,
                 GDestroyNotify  notify)
@@ -227,6 +395,25 @@ g_private_init (GPrivate       *key,
   key->ready = TRUE;
 }
 
+/**
+ * g_private_get:
+ * @private_key: a #GPrivate
+ *
+ * Returns the pointer keyed to @private_key for the current thread. If
+ * g_private_set() hasn't been called for the current @private_key and
+ * thread yet, this pointer will be %NULL.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will return the value of @private_key
+ * casted to #gpointer. Note however, that private data set
+ * <emphasis>before</emphasis> g_thread_init() will
+ * <emphasis>not</emphasis> be retained <emphasis>after</emphasis> the
+ * call. Instead, %NULL will be returned in all threads directly after
+ * g_thread_init(), regardless of any g_private_set() calls issued
+ * before threading system initialization.
+ *
+ * Returns: the corresponding pointer
+ */
 gpointer
 g_private_get (GPrivate *key)
 {
@@ -237,6 +424,17 @@ g_private_get (GPrivate *key)
   return pthread_getspecific (key->key);
 }
 
+/**
+ * g_private_set:
+ * @private_key: a #GPrivate
+ * @data: the new pointer
+ *
+ * Sets the pointer keyed to @private_key for the current thread.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will set @private_key to @data casted to
+ * #GPrivate*. See g_private_get() for resulting caveats.
+ */
 void
 g_private_set (GPrivate *key,
                gpointer  value)
@@ -282,74 +480,6 @@ g_private_set (GPrivate *key,
 
 #define posix_check_cmd(cmd) posix_check_err (cmd, #cmd)
 
-#ifdef G_ENABLE_DEBUG
-static gboolean posix_check_cmd_prio_warned = FALSE;
-# define posix_check_cmd_prio(cmd) G_STMT_START{                       \
-    int err = (cmd);                                                   \
-    if (err == EPERM)                                                  \
-      {                                                                \
-        if (!posix_check_cmd_prio_warned)                              \
-          {                                                            \
-            posix_check_cmd_prio_warned = TRUE;                                \
-            g_warning ("Priorities can only be changed "               \
-                        "(resp. increased) by root.");                         \
-          }                                                            \
-      }                                                                        \
-    else                                                               \
-      posix_check_err (err, #cmd);                                     \
-     }G_STMT_END
-#else /* G_ENABLE_DEBUG */
-# define posix_check_cmd_prio(cmd) G_STMT_START{                       \
-    int err = (cmd);                                                   \
-    if (err != EPERM)                                                  \
-      posix_check_err (err, #cmd);                                     \
-     }G_STMT_END
-#endif /* G_ENABLE_DEBUG */
-
-#if defined (POSIX_MIN_PRIORITY) && defined (POSIX_MAX_PRIORITY)
-# define HAVE_PRIORITIES 1
-static gint priority_normal_value;
-# ifdef __FreeBSD__
-   /* FreeBSD threads use different priority values from the POSIX_
-    * defines so we just set them here. The corresponding macros
-    * PTHREAD_MIN_PRIORITY and PTHREAD_MAX_PRIORITY are implied to be
-    * exported by the docs, but they aren't.
-    */
-#  define PRIORITY_LOW_VALUE      0
-#  define PRIORITY_URGENT_VALUE   31
-# else /* !__FreeBSD__ */
-#  define PRIORITY_LOW_VALUE      POSIX_MIN_PRIORITY
-#  define PRIORITY_URGENT_VALUE   POSIX_MAX_PRIORITY
-# endif /* !__FreeBSD__ */
-# define PRIORITY_NORMAL_VALUE    priority_normal_value
-
-# define PRIORITY_HIGH_VALUE \
-    ((PRIORITY_NORMAL_VALUE + PRIORITY_URGENT_VALUE * 2) / 3)
-
-static gint
-g_thread_priority_map (GThreadPriority priority)
-{
-  switch (priority)
-    {
-    case G_THREAD_PRIORITY_LOW:
-      return PRIORITY_LOW_VALUE;
-
-    case G_THREAD_PRIORITY_NORMAL:
-      return PRIORITY_NORMAL_VALUE;
-
-    case G_THREAD_PRIORITY_HIGH:
-      return PRIORITY_HIGH_VALUE;
-
-    case G_THREAD_PRIORITY_URGENT:
-      return PRIORITY_URGENT_VALUE;
-
-    default:
-      g_assert_not_reached ();
-    }
-}
-
-#endif /* POSIX_MIN_PRIORITY && POSIX_MAX_PRIORITY */
-
 static gulong g_thread_min_stack_size = 0;
 
 #define G_MUTEX_SIZE (sizeof (pthread_mutex_t))
@@ -360,32 +490,22 @@ _g_thread_impl_init(void)
 #ifdef _SC_THREAD_STACK_MIN
   g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0);
 #endif /* _SC_THREAD_STACK_MIN */
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    int policy;
-    posix_check_cmd (pthread_getschedparam (pthread_self(), &policy, &sched));
-    priority_normal_value = sched.sched_priority;
-  }
-#endif /* HAVE_PRIORITIES */
 }
 
-static void
-g_thread_create_posix_impl (GThreadFunc thread_func,
-                           gpointer arg,
-                           gulong stack_size,
-                           gboolean joinable,
-                           gboolean bound,
-                           GThreadPriority priority,
-                           gpointer thread,
-                           GError **error)
+void
+g_system_thread_create (GThreadFunc       thread_func,
+                        gpointer          arg,
+                        gulong            stack_size,
+                        gboolean          joinable,
+                        gboolean          bound,
+                        GThreadPriority   priority,
+                        gpointer          thread,
+                        GError          **error)
 {
   pthread_attr_t attr;
   gint ret;
 
   g_return_if_fail (thread_func);
-  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
-  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
 
   posix_check_cmd (pthread_attr_init (&attr));
 
@@ -409,14 +529,6 @@ g_thread_create_posix_impl (GThreadFunc thread_func,
   posix_check_cmd (pthread_attr_setdetachstate (&attr,
           joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
 
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    posix_check_cmd (pthread_attr_getschedparam (&attr, &sched));
-    sched.sched_priority = g_thread_priority_map (priority);
-    posix_check_cmd_prio (pthread_attr_setschedparam (&attr, &sched));
-  }
-#endif /* HAVE_PRIORITIES */
   ret = pthread_create (thread, &attr, (void* (*)(void*))thread_func, arg);
 
   posix_check_cmd (pthread_attr_destroy (&attr));
@@ -431,79 +543,46 @@ g_thread_create_posix_impl (GThreadFunc thread_func,
   posix_check_err (ret, "pthread_create");
 }
 
-static void
-g_thread_yield_posix_impl (void)
+/**
+ * g_thread_yield:
+ *
+ * Gives way to other threads waiting to be scheduled.
+ *
+ * This function is often used as a method to make busy wait less evil.
+ * But in most cases you will encounter, there are better methods to do
+ * that. So in general you shouldn't use this function.
+ */
+void
+g_thread_yield (void)
 {
   sched_yield ();
 }
 
-static void
-g_thread_join_posix_impl (gpointer thread)
+void
+g_system_thread_join (gpointer thread)
 {
   gpointer ignore;
   posix_check_cmd (pthread_join (*(pthread_t*)thread, &ignore));
 }
 
-static void
-g_thread_exit_posix_impl (void)
+void
+g_system_thread_exit (void)
 {
   pthread_exit (NULL);
 }
 
-static void
-g_thread_set_priority_posix_impl (gpointer thread, GThreadPriority priority)
-{
-  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
-  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    int policy;
-    posix_check_cmd (pthread_getschedparam (*(pthread_t*)thread, &policy,
-                                           &sched));
-    sched.sched_priority = g_thread_priority_map (priority);
-    posix_check_cmd_prio (pthread_setschedparam (*(pthread_t*)thread, policy,
-                                                &sched));
-  }
-#endif /* HAVE_PRIORITIES */
-}
-
-static void
-g_thread_self_posix_impl (gpointer thread)
+void
+g_system_thread_self (gpointer thread)
 {
   *(pthread_t*)thread = pthread_self();
 }
 
-static gboolean
-g_thread_equal_posix_impl (gpointer thread1, gpointer thread2)
+gboolean
+g_system_thread_equal (gpointer thread1,
+                       gpointer thread2)
 {
   return (pthread_equal (*(pthread_t*)thread1, *(pthread_t*)thread2) != 0);
 }
 
 /* {{{1 Epilogue */
-GThreadFunctions g_thread_functions_for_glib_use =
-{
-  g_mutex_new,
-  g_mutex_lock,
-  g_mutex_trylock,
-  g_mutex_unlock,
-  g_mutex_free,
-  g_cond_new,
-  g_cond_signal,
-  g_cond_broadcast,
-  g_cond_wait,
-  g_cond_timed_wait,
-  g_cond_free,
-  g_private_new,
-  g_private_get,
-  g_private_set,
-  g_thread_create_posix_impl,
-  g_thread_yield_posix_impl,
-  g_thread_join_posix_impl,
-  g_thread_exit_posix_impl,
-  g_thread_set_priority_posix_impl,
-  g_thread_self_posix_impl,
-  g_thread_equal_posix_impl
-};
-
 /* vim:set foldmethod=marker: */