- * <note><para>Calling g_static_mutex_free() on a locked mutex may
- * result in undefined behaviour.</para></note>
- **/
-void
-g_static_mutex_free (GStaticMutex* mutex)
-{
- GMutex **runtime_mutex;
-
- g_return_if_fail (mutex);
-
- /* The runtime_mutex is the first (or only) member of GStaticMutex,
- * see both versions (of glibconfig.h) in configure.ac. Note, that
- * this variable is NULL, if g_thread_init() hasn't been called or
- * if we're using the default thread implementation and it provides
- * static mutexes. */
- runtime_mutex = ((GMutex**)mutex);
-
- if (*runtime_mutex)
- g_mutex_free (*runtime_mutex);
-
- *runtime_mutex = NULL;
-}
-
-/* ------------------------------------------------------------------------ */
-
-/**
- * GStaticRecMutex:
- *
- * A #GStaticRecMutex works like a #GStaticMutex, but it can be locked
- * multiple times by one thread. If you enter it n times, you have to
- * unlock it n times again to let other threads lock it. An exception
- * is the function g_static_rec_mutex_unlock_full(): that allows you to
- * unlock a #GStaticRecMutex completely returning the depth, (i.e. the
- * number of times this mutex was locked). The depth can later be used
- * to restore the state of the #GStaticRecMutex by calling
- * g_static_rec_mutex_lock_full().
- *
- * Even though #GStaticRecMutex is not opaque, it should only be used
- * with the following functions.
- *
- * All of the <function>g_static_rec_mutex_*</function> functions can
- * be used even if g_thread_init() has not been called. Then they do
- * nothing, apart from <function>g_static_rec_mutex_trylock</function>,
- * which does nothing but returning %TRUE.
- **/
-
-/**
- * G_STATIC_REC_MUTEX_INIT:
- *
- * A #GStaticRecMutex must be initialized with this macro before it can
- * be used. This macro can used be to initialize a variable, but it
- * cannot be assigned to a variable. In that case you have to use
- * g_static_rec_mutex_init().
- *
- * <informalexample>
- * <programlisting>
- * GStaticRecMutex my_mutex = G_STATIC_REC_MUTEX_INIT;
- * </programlisting>
- </informalexample>
- **/
-
-/**
- * g_static_rec_mutex_init:
- * @mutex: a #GStaticRecMutex to be initialized.
- *
- * A #GStaticRecMutex must be initialized with this function before it
- * can be used. Alternatively you can initialize it with
- * #G_STATIC_REC_MUTEX_INIT.
- **/
-void
-g_static_rec_mutex_init (GStaticRecMutex *mutex)
-{
- static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
-
- g_return_if_fail (mutex);
-
- *mutex = init_mutex;
-}
-
-/**
- * g_static_rec_mutex_lock:
- * @mutex: a #GStaticRecMutex to lock.
- *
- * Locks @mutex. If @mutex is already locked by another thread, the
- * current thread will block until @mutex is unlocked by the other
- * thread. If @mutex is already locked by the calling thread, this
- * functions increases the depth of @mutex and returns immediately.
- **/
-void
-g_static_rec_mutex_lock (GStaticRecMutex* mutex)
-{
- GSystemThread self;
-
- g_return_if_fail (mutex);
-
- if (!g_thread_supported ())
- return;
-
- G_THREAD_UF (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;
-}
-
-/**
- * g_static_rec_mutex_trylock:
- * @mutex: a #GStaticRecMutex to lock.
- * @Returns: %TRUE, if @mutex could be locked.
- *
- * Tries to lock @mutex. If @mutex is already locked by another thread,
- * it immediately returns %FALSE. Otherwise it locks @mutex and returns
- * %TRUE. If @mutex is already locked by the calling thread, this
- * functions increases the depth of @mutex and immediately returns
- * %TRUE.
- **/
-gboolean
-g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
-{
- GSystemThread self;
-
- g_return_val_if_fail (mutex, FALSE);
-
- if (!g_thread_supported ())
- return TRUE;
-
- G_THREAD_UF (thread_self, (&self));
-
- if (g_system_thread_equal (&self, &mutex->owner))
- {
- mutex->depth++;
- return TRUE;
- }
-
- if (!g_static_mutex_trylock (&mutex->mutex))
- return FALSE;
-
- g_system_thread_assign (mutex->owner, self);
- mutex->depth = 1;
- return TRUE;
-}
-
-/**
- * g_static_rec_mutex_unlock:
- * @mutex: a #GStaticRecMutex to unlock.
- *
- * Unlocks @mutex. Another thread will be allowed to lock @mutex only
- * when it has been unlocked as many times as it had been locked
- * before. If @mutex is completely unlocked and another thread is
- * blocked in a g_static_rec_mutex_lock() call for @mutex, it will be
- * woken and can lock @mutex itself.
- **/
-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);
-}
-
-/**
- * g_static_rec_mutex_lock_full:
- * @mutex: a #GStaticRecMutex to lock.
- * @depth: number of times this mutex has to be unlocked to be
- * completely unlocked.
- *
- * Works like calling g_static_rec_mutex_lock() for @mutex @depth times.
- **/
-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;
-
- G_THREAD_UF (thread_self, (&self));
-
- if (g_system_thread_equal (&self, &mutex->owner))
- {
- mutex->depth += depth;
- return;
- }
- g_static_mutex_lock (&mutex->mutex);
- g_system_thread_assign (mutex->owner, self);
- mutex->depth = depth;
-}
-
-/**
- * g_static_rec_mutex_unlock_full:
- * @mutex: a #GStaticRecMutex to completely unlock.
- * @Returns: number of times @mutex has been locked by the current
- * thread.
- *
- * Completely unlocks @mutex. If another thread is blocked in a
- * g_static_rec_mutex_lock() call for @mutex, it will be woken and can
- * lock @mutex itself. This function returns the number of times that
- * @mutex has been locked by the current thread. To restore the state
- * before the call to g_static_rec_mutex_unlock_full() you can call
- * g_static_rec_mutex_lock_full() with the depth returned by this
- * function.
- **/
-guint
-g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
-{
- guint depth;
-
- g_return_val_if_fail (mutex, 0);
-
- if (!g_thread_supported ())
- return 1;
-
- depth = mutex->depth;
-
- g_system_thread_assign (mutex->owner, zero_thread);
- mutex->depth = 0;
- g_static_mutex_unlock (&mutex->mutex);
-
- return depth;
-}
-
-/**
- * g_static_rec_mutex_free:
- * @mutex: a #GStaticRecMutex to be freed.
- *
- * Releases all resources allocated to a #GStaticRecMutex.
- *
- * You don't have to call this functions for a #GStaticRecMutex with an
- * unbounded lifetime, i.e. objects declared 'static', but if you have
- * a #GStaticRecMutex as a member of a structure and the structure is
- * freed, you should also free the #GStaticRecMutex.
- **/
-void
-g_static_rec_mutex_free (GStaticRecMutex *mutex)
-{
- g_return_if_fail (mutex);
-
- g_static_mutex_free (&mutex->mutex);
-}
-
-/* GStaticPrivate {{{1 ---------------------------------------------------- */
-
-/**
- * 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 (&current_number_key);
- *
- * if (!current_number)
- * {
- * current_number = g_new (int,1);
- * *current_number = 0;
- * g_static_private_set (&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.
- *
- * <informalexample>
- * <programlisting>
- * GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
- * </programlisting>
- * </informalexample>
- **/
-
-/**
- * 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.
- * @Returns: the corresponding pointer.
- *
- * Works like g_private_get() only for a #GStaticPrivate.
- *
- * This function works even if g_thread_init() has not yet been called.
- **/
-gpointer
-g_static_private_get (GStaticPrivate *private_key)
-{
- GRealThread *self = (GRealThread*) g_thread_self ();
- GArray *array;
- gpointer ret = NULL;
-
- LOCK_PRIVATE_DATA (self);
-
- array = self->private_data;
-
- if (array && private_key->index != 0 && private_key->index <= array->len)
- ret = g_array_index (array, GStaticPrivateNode,
- private_key->index - 1).data;
-
- UNLOCK_PRIVATE_DATA (self);
- 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;
- gpointer ddata = NULL;
- GDestroyNotify ddestroy = NULL;
-
- 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);
- }
-
- LOCK_PRIVATE_DATA (self);
-
- 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);
-
- ddata = node->data;
- ddestroy = node->destroy;
-
- node->data = data;
- node->destroy = notify;
-
- UNLOCK_PRIVATE_DATA (self);
-
- if (ddestroy)
- ddestroy (ddata);
-}
-
-/**
- * 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;
- GRealThread *thread, *next;
- GArray *garbage = NULL;
-
- if (!idx)
- return;
-
- private_key->index = 0;
-
- G_LOCK (g_thread);
-
- thread = g_thread_all_threads;
-
- for (thread = g_thread_all_threads; thread; thread = next)
- {
- GArray *array;
-
- next = thread->next;
-
- LOCK_PRIVATE_DATA (thread);
-
- array = thread->private_data;
-
- if (array && idx <= array->len)
- {
- GStaticPrivateNode *node = &g_array_index (array,
- GStaticPrivateNode,
- idx - 1);
- gpointer ddata = node->data;
- GDestroyNotify ddestroy = node->destroy;
-
- node->data = NULL;
- node->destroy = NULL;
-
- if (ddestroy)
- {
- /* defer non-trivial destruction til after we've finished
- * iterating, since we must continue to hold the lock */
- if (garbage == NULL)
- garbage = g_array_new (FALSE, TRUE,
- sizeof (GStaticPrivateNode));
-
- g_array_set_size (garbage, garbage->len + 1);
-
- node = &g_array_index (garbage, GStaticPrivateNode,
- garbage->len - 1);
- node->data = ddata;
- node->destroy = ddestroy;
- }
- }
-
- UNLOCK_PRIVATE_DATA (thread);
- }
- g_thread_free_indices = g_slist_prepend (g_thread_free_indices,
- GUINT_TO_POINTER (idx));
- G_UNLOCK (g_thread);
-
- if (garbage)
- {
- guint i;
-
- for (i = 0; i < garbage->len; i++)
- {
- GStaticPrivateNode *node;
-
- node = &g_array_index (garbage, GStaticPrivateNode, i);
- node->destroy (node->data);
- }
-
- g_array_free (garbage, TRUE);
- }
-}
-
-/* GThread Extra Functions {{{1 ------------------------------------------- */
-static void
-g_thread_cleanup (gpointer data)
-{
- if (data)
- {
- GRealThread* thread = data;
- GArray *array;
-
- LOCK_PRIVATE_DATA (thread);
- array = thread->private_data;
- thread->private_data = NULL;
- UNLOCK_PRIVATE_DATA (thread);
-
- 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);
- }
-
- /* We only free the thread structure, if it isn't joinable. If
- it is, the structure is freed in g_thread_join */
- if (!thread->thread.joinable)
- {
- 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);
-
- /* Just to make sure, this isn't used any more */
- g_system_thread_assign (thread->system_thread, zero_thread);
- g_free (thread);
- }
- }
-}
-
-static void
-g_thread_fail (void)
-{
- g_error ("The thread system is not yet initialized.");
-}
-
-#define G_NSEC_PER_SEC 1000000000
-
-static guint64
-gettime (void)
-{
- return g_get_monotonic_time () * 1000;
-}
-
-static gpointer
-g_thread_create_proxy (gpointer data)