+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
+2001-02-13 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread.c, gthread.h: Added functions g_static_rec_mutex_init,
+ g_static_rec_mutex_free, g_static_private_init,
+ g_static_private_free, g_static_rw_lock_init to allow the usage of
+ all those types dynamically. (g_static_rw_lock_free already
+ existed). Aditionally freed static_private indeces are reused
+ now. Untill now the array would just grow if you would use more
+ and more static_private. That required adding a slist of all
+ running threads, which could potentially be of good use later. It
+ is not exported however. Renamed a LOCK and small indentation
+ fixes.
+
+ * tests/thread-test.c: Test the new static_private index freing
+ and reusing feature.
+
Mon Feb 12 15:01:09 2001 Owen Taylor <otaylor@redhat.com>
* configure.in (gtk_doc_min_version): Add check for gtk-doc version.
#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
GQuark
-g_thread_error_quark()
+g_thread_error_quark (void)
{
static GQuark quark;
if (!quark)
/* Local data */
static GMutex *g_mutex_protect_static_mutex_allocation = NULL;
-static GMutex *g_thread_specific_mutex = NULL;
static GPrivate *g_thread_specific_private = NULL;
+static GSList *g_thread_all_threads = NULL;
+static GSList *g_thread_free_indeces = NULL;
+
+G_LOCK_DEFINE_STATIC (g_thread);
/* This must be called only once, before any threads are created.
* It will only be called from g_thread_init() in -lgthread.
G_THREAD_UF (private_set, (g_thread_specific_private, main_thread));
G_THREAD_UF (thread_self, (&main_thread->system_thread));
- g_mutex_protect_static_mutex_allocation = g_mutex_new();
- g_thread_specific_mutex = g_mutex_new();
+ g_mutex_protect_static_mutex_allocation = g_mutex_new ();
+}
+
+void
+g_static_mutex_init (GStaticMutex *mutex)
+{
+ static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+
+ g_return_if_fail (mutex);
+
+ memcpy (mutex, &init_mutex, sizeof (GStaticMutex));
}
GMutex *
g_mutex_lock (g_mutex_protect_static_mutex_allocation);
if (!(*mutex))
- *mutex = g_mutex_new();
+ *mutex = g_mutex_new ();
g_mutex_unlock (g_mutex_protect_static_mutex_allocation);
return *mutex;
}
-void
-g_static_mutex_init (GStaticMutex *mutex)
-{
- static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
-
- g_return_if_fail (mutex);
-
- memcpy (mutex, &init_mutex, sizeof (GStaticMutex));
-}
-
void
g_static_mutex_free (GStaticMutex* mutex)
{
*runtime_mutex = NULL;
}
+void
+g_static_rec_mutex_init (GStaticRecMutex *mutex)
+{
+ static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
+
+ g_return_if_fail (mutex);
+
+ memcpy (mutex, &init_mutex, sizeof (GStaticRecMutex));
+}
+
void
g_static_rec_mutex_lock (GStaticRecMutex* mutex)
{
return depth;
}
+void
+g_static_rec_mutex_free (GStaticRecMutex *mutex)
+{
+ g_return_if_fail (mutex);
+
+ g_static_mutex_free (&mutex->mutex);
+}
+
+void
+g_static_private_init (GStaticPrivate *private_key)
+{
+ private_key->index = 0;
+}
gpointer
g_static_private_get (GStaticPrivate *private_key)
if (!private_key->index)
{
- g_mutex_lock (g_thread_specific_mutex);
+ G_LOCK (g_thread);
if (!private_key->index)
- private_key->index = ++next_index;
+ {
+ if (g_thread_free_indeces)
+ {
+ private_key->index =
+ GPOINTER_TO_UINT (g_thread_free_indeces->data);
+ g_thread_free_indeces =
+ g_slist_delete_link (g_thread_free_indeces,
+ g_thread_free_indeces);
+ }
+ else
+ private_key->index = ++next_index;
+ }
- g_mutex_unlock (g_thread_specific_mutex);
+ G_UNLOCK (g_thread);
}
if (private_key->index > array->len)
}
}
+void
+g_static_private_free (GStaticPrivate *private_key)
+{
+ GStaticPrivate copied_key;
+ GSList *list;
+
+ copied_key.index = private_key->index;
+ private_key->index = 0;
+
+ if (!copied_key.index)
+ return;
+
+ G_LOCK (g_thread);
+ list = g_thread_all_threads;
+ while (list)
+ {
+ GThread *thread = list->data;
+ list = list->next;
+
+ G_UNLOCK (g_thread);
+ g_static_private_set_for_thread (&copied_key, thread, NULL, NULL);
+ G_LOCK (g_thread);
+ }
+ g_thread_free_indeces =
+ g_slist_prepend (g_thread_free_indeces,
+ GUINT_TO_POINTER (copied_key.index));
+ G_UNLOCK (g_thread);
+}
+
static void
g_thread_cleanup (gpointer data)
{
it is, the structure is freed in g_thread_join */
if (!thread->thread.joinable)
{
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_remove (g_thread_all_threads, data);
+ 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);
g_error ("The thread system is not yet initialized.");
}
-G_LOCK_DEFINE_STATIC (g_thread_create);
-
static void
g_thread_create_proxy (gpointer data)
{
/* the lock makes sure, that thread->system_thread is written,
before thread->func is called. See g_thread_create. */
- G_LOCK (g_thread_create);
- G_UNLOCK (g_thread_create);
+ G_LOCK (g_thread);
+ G_UNLOCK (g_thread);
thread->func (thread->arg);
}
result->func = thread_func;
result->arg = arg;
result->private_data = NULL;
- G_LOCK (g_thread_create);
+ G_LOCK (g_thread);
G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
stack_size, joinable, bound, priority,
&result->system_thread, &local_error));
- G_UNLOCK (g_thread_create);
+ g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result);
+ G_UNLOCK (g_thread);
if (local_error)
{
G_THREAD_UF (thread_join, (&real->system_thread));
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
+ G_UNLOCK (g_thread);
+
/* Just to make sure, this isn't used any more */
thread->joinable = 0;
g_system_thread_assign (real->system_thread, zero_thread);
}
GThread*
-g_thread_self()
+g_thread_self (void)
{
GRealThread* thread = g_private_get (g_thread_specific_private);
if (g_thread_supported ())
G_THREAD_UF (thread_self, (&thread->system_thread));
- g_private_set (g_thread_specific_private, thread);
+ g_private_set (g_thread_specific_private, thread);
+
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
+ G_UNLOCK (g_thread);
}
return (GThread*)thread;
}
-static void inline g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
+void
+g_static_rw_lock_init (GStaticRWLock* lock)
+{
+ static GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
+
+ g_return_if_fail (lock);
+
+ memcpy (lock, &init_lock, sizeof (GStaticRWLock));
+}
+
+static void inline
+g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
{
if (!*cond)
*cond = g_cond_new ();
g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
}
-static void inline g_static_rw_lock_signal (GStaticRWLock* lock)
+static void inline
+g_static_rw_lock_signal (GStaticRWLock* lock)
{
if (lock->want_to_write && lock->write_cond)
g_cond_signal (lock->write_cond);
g_cond_broadcast (lock->read_cond);
}
-void g_static_rw_lock_reader_lock (GStaticRWLock* lock)
+void
+g_static_rw_lock_reader_lock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
+gboolean
+g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
{
gboolean ret_val = FALSE;
return ret_val;
}
-void g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
+void
+g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-void g_static_rw_lock_writer_lock (GStaticRWLock* lock)
+void
+g_static_rw_lock_writer_lock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
+gboolean
+g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
{
gboolean ret_val = FALSE;
return ret_val;
}
-void g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
+void
+g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-void g_static_rw_lock_free (GStaticRWLock* lock)
+void
+g_static_rw_lock_free (GStaticRWLock* lock)
{
g_return_if_fail (lock);
if (lock->read_cond)
- g_cond_free (lock->read_cond);
+ {
+ g_cond_free (lock->read_cond);
+ lock->read_cond = NULL;
+ }
if (lock->write_cond)
- g_cond_free (lock->write_cond);
-
+ {
+ g_cond_free (lock->write_cond);
+ lock->write_cond = NULL;
+ }
+ g_static_mutex_free (&lock->mutex);
}
-
/* GLib Thread support
*/
-extern GQuark g_thread_error_quark();
-#define G_THREAD_ERROR g_thread_error_quark()
+extern GQuark g_thread_error_quark (void);
+#define G_THREAD_ERROR g_thread_error_quark ()
typedef enum
{
guint index;
};
#define G_STATIC_PRIVATE_INIT { 0 }
-gpointer g_static_private_get (GStaticPrivate *private_key);
-void g_static_private_set (GStaticPrivate *private_key,
- gpointer data,
- GDestroyNotify notify);
-gpointer g_static_private_get_for_thread (GStaticPrivate *private_key,
- GThread *thread);
-void g_static_private_set_for_thread (GStaticPrivate *private_key,
- GThread *thread,
- gpointer data,
- GDestroyNotify notify);
+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);
+gpointer g_static_private_get_for_thread (GStaticPrivate *private_key,
+ GThread *thread);
+void g_static_private_set_for_thread (GStaticPrivate *private_key,
+ GThread *thread,
+ gpointer data,
+ GDestroyNotify notify);
+void g_static_private_free (GStaticPrivate *private_key);
typedef struct _GStaticRecMutex GStaticRecMutex;
struct _GStaticRecMutex
};
#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
+void g_static_rec_mutex_init (GStaticRecMutex *mutex);
void g_static_rec_mutex_lock (GStaticRecMutex *mutex);
gboolean g_static_rec_mutex_trylock (GStaticRecMutex *mutex);
void g_static_rec_mutex_unlock (GStaticRecMutex *mutex);
void g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
guint depth);
guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex);
+void g_static_rec_mutex_free (GStaticRecMutex *mutex);
typedef struct _GStaticRWLock GStaticRWLock;
struct _GStaticRWLock
#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, FALSE }
+void g_static_rw_lock_init (GStaticRWLock* lock);
void g_static_rw_lock_reader_lock (GStaticRWLock* lock);
gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock);
void g_static_rw_lock_reader_unlock (GStaticRWLock* lock);
void g_static_rw_lock_writer_lock (GStaticRWLock* lock);
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);
+void g_static_rw_lock_free (GStaticRWLock* lock);
/* these are some convenience macros that expand to nothing if GLib
* was configured with --disable-threads. for using StaticMutexes,
#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
GQuark
-g_thread_error_quark()
+g_thread_error_quark (void)
{
static GQuark quark;
if (!quark)
/* Local data */
static GMutex *g_mutex_protect_static_mutex_allocation = NULL;
-static GMutex *g_thread_specific_mutex = NULL;
static GPrivate *g_thread_specific_private = NULL;
+static GSList *g_thread_all_threads = NULL;
+static GSList *g_thread_free_indeces = NULL;
+
+G_LOCK_DEFINE_STATIC (g_thread);
/* This must be called only once, before any threads are created.
* It will only be called from g_thread_init() in -lgthread.
G_THREAD_UF (private_set, (g_thread_specific_private, main_thread));
G_THREAD_UF (thread_self, (&main_thread->system_thread));
- g_mutex_protect_static_mutex_allocation = g_mutex_new();
- g_thread_specific_mutex = g_mutex_new();
+ g_mutex_protect_static_mutex_allocation = g_mutex_new ();
+}
+
+void
+g_static_mutex_init (GStaticMutex *mutex)
+{
+ static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+
+ g_return_if_fail (mutex);
+
+ memcpy (mutex, &init_mutex, sizeof (GStaticMutex));
}
GMutex *
g_mutex_lock (g_mutex_protect_static_mutex_allocation);
if (!(*mutex))
- *mutex = g_mutex_new();
+ *mutex = g_mutex_new ();
g_mutex_unlock (g_mutex_protect_static_mutex_allocation);
return *mutex;
}
-void
-g_static_mutex_init (GStaticMutex *mutex)
-{
- static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
-
- g_return_if_fail (mutex);
-
- memcpy (mutex, &init_mutex, sizeof (GStaticMutex));
-}
-
void
g_static_mutex_free (GStaticMutex* mutex)
{
*runtime_mutex = NULL;
}
+void
+g_static_rec_mutex_init (GStaticRecMutex *mutex)
+{
+ static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
+
+ g_return_if_fail (mutex);
+
+ memcpy (mutex, &init_mutex, sizeof (GStaticRecMutex));
+}
+
void
g_static_rec_mutex_lock (GStaticRecMutex* mutex)
{
return depth;
}
+void
+g_static_rec_mutex_free (GStaticRecMutex *mutex)
+{
+ g_return_if_fail (mutex);
+
+ g_static_mutex_free (&mutex->mutex);
+}
+
+void
+g_static_private_init (GStaticPrivate *private_key)
+{
+ private_key->index = 0;
+}
gpointer
g_static_private_get (GStaticPrivate *private_key)
if (!private_key->index)
{
- g_mutex_lock (g_thread_specific_mutex);
+ G_LOCK (g_thread);
if (!private_key->index)
- private_key->index = ++next_index;
+ {
+ if (g_thread_free_indeces)
+ {
+ private_key->index =
+ GPOINTER_TO_UINT (g_thread_free_indeces->data);
+ g_thread_free_indeces =
+ g_slist_delete_link (g_thread_free_indeces,
+ g_thread_free_indeces);
+ }
+ else
+ private_key->index = ++next_index;
+ }
- g_mutex_unlock (g_thread_specific_mutex);
+ G_UNLOCK (g_thread);
}
if (private_key->index > array->len)
}
}
+void
+g_static_private_free (GStaticPrivate *private_key)
+{
+ GStaticPrivate copied_key;
+ GSList *list;
+
+ copied_key.index = private_key->index;
+ private_key->index = 0;
+
+ if (!copied_key.index)
+ return;
+
+ G_LOCK (g_thread);
+ list = g_thread_all_threads;
+ while (list)
+ {
+ GThread *thread = list->data;
+ list = list->next;
+
+ G_UNLOCK (g_thread);
+ g_static_private_set_for_thread (&copied_key, thread, NULL, NULL);
+ G_LOCK (g_thread);
+ }
+ g_thread_free_indeces =
+ g_slist_prepend (g_thread_free_indeces,
+ GUINT_TO_POINTER (copied_key.index));
+ G_UNLOCK (g_thread);
+}
+
static void
g_thread_cleanup (gpointer data)
{
it is, the structure is freed in g_thread_join */
if (!thread->thread.joinable)
{
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_remove (g_thread_all_threads, data);
+ 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);
g_error ("The thread system is not yet initialized.");
}
-G_LOCK_DEFINE_STATIC (g_thread_create);
-
static void
g_thread_create_proxy (gpointer data)
{
/* the lock makes sure, that thread->system_thread is written,
before thread->func is called. See g_thread_create. */
- G_LOCK (g_thread_create);
- G_UNLOCK (g_thread_create);
+ G_LOCK (g_thread);
+ G_UNLOCK (g_thread);
thread->func (thread->arg);
}
result->func = thread_func;
result->arg = arg;
result->private_data = NULL;
- G_LOCK (g_thread_create);
+ G_LOCK (g_thread);
G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
stack_size, joinable, bound, priority,
&result->system_thread, &local_error));
- G_UNLOCK (g_thread_create);
+ g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result);
+ G_UNLOCK (g_thread);
if (local_error)
{
G_THREAD_UF (thread_join, (&real->system_thread));
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
+ G_UNLOCK (g_thread);
+
/* Just to make sure, this isn't used any more */
thread->joinable = 0;
g_system_thread_assign (real->system_thread, zero_thread);
}
GThread*
-g_thread_self()
+g_thread_self (void)
{
GRealThread* thread = g_private_get (g_thread_specific_private);
if (g_thread_supported ())
G_THREAD_UF (thread_self, (&thread->system_thread));
- g_private_set (g_thread_specific_private, thread);
+ g_private_set (g_thread_specific_private, thread);
+
+ G_LOCK (g_thread);
+ g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
+ G_UNLOCK (g_thread);
}
return (GThread*)thread;
}
-static void inline g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
+void
+g_static_rw_lock_init (GStaticRWLock* lock)
+{
+ static GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
+
+ g_return_if_fail (lock);
+
+ memcpy (lock, &init_lock, sizeof (GStaticRWLock));
+}
+
+static void inline
+g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
{
if (!*cond)
*cond = g_cond_new ();
g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
}
-static void inline g_static_rw_lock_signal (GStaticRWLock* lock)
+static void inline
+g_static_rw_lock_signal (GStaticRWLock* lock)
{
if (lock->want_to_write && lock->write_cond)
g_cond_signal (lock->write_cond);
g_cond_broadcast (lock->read_cond);
}
-void g_static_rw_lock_reader_lock (GStaticRWLock* lock)
+void
+g_static_rw_lock_reader_lock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
+gboolean
+g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
{
gboolean ret_val = FALSE;
return ret_val;
}
-void g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
+void
+g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-void g_static_rw_lock_writer_lock (GStaticRWLock* lock)
+void
+g_static_rw_lock_writer_lock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
+gboolean
+g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
{
gboolean ret_val = FALSE;
return ret_val;
}
-void g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
+void
+g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
{
g_return_if_fail (lock);
g_static_mutex_unlock (&lock->mutex);
}
-void g_static_rw_lock_free (GStaticRWLock* lock)
+void
+g_static_rw_lock_free (GStaticRWLock* lock)
{
g_return_if_fail (lock);
if (lock->read_cond)
- g_cond_free (lock->read_cond);
+ {
+ g_cond_free (lock->read_cond);
+ lock->read_cond = NULL;
+ }
if (lock->write_cond)
- g_cond_free (lock->write_cond);
-
+ {
+ g_cond_free (lock->write_cond);
+ lock->write_cond = NULL;
+ }
+ g_static_mutex_free (&lock->mutex);
}
-
/* GLib Thread support
*/
-extern GQuark g_thread_error_quark();
-#define G_THREAD_ERROR g_thread_error_quark()
+extern GQuark g_thread_error_quark (void);
+#define G_THREAD_ERROR g_thread_error_quark ()
typedef enum
{
guint index;
};
#define G_STATIC_PRIVATE_INIT { 0 }
-gpointer g_static_private_get (GStaticPrivate *private_key);
-void g_static_private_set (GStaticPrivate *private_key,
- gpointer data,
- GDestroyNotify notify);
-gpointer g_static_private_get_for_thread (GStaticPrivate *private_key,
- GThread *thread);
-void g_static_private_set_for_thread (GStaticPrivate *private_key,
- GThread *thread,
- gpointer data,
- GDestroyNotify notify);
+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);
+gpointer g_static_private_get_for_thread (GStaticPrivate *private_key,
+ GThread *thread);
+void g_static_private_set_for_thread (GStaticPrivate *private_key,
+ GThread *thread,
+ gpointer data,
+ GDestroyNotify notify);
+void g_static_private_free (GStaticPrivate *private_key);
typedef struct _GStaticRecMutex GStaticRecMutex;
struct _GStaticRecMutex
};
#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
+void g_static_rec_mutex_init (GStaticRecMutex *mutex);
void g_static_rec_mutex_lock (GStaticRecMutex *mutex);
gboolean g_static_rec_mutex_trylock (GStaticRecMutex *mutex);
void g_static_rec_mutex_unlock (GStaticRecMutex *mutex);
void g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
guint depth);
guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex);
+void g_static_rec_mutex_free (GStaticRecMutex *mutex);
typedef struct _GStaticRWLock GStaticRWLock;
struct _GStaticRWLock
#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, FALSE }
+void g_static_rw_lock_init (GStaticRWLock* lock);
void g_static_rw_lock_reader_lock (GStaticRWLock* lock);
gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock);
void g_static_rw_lock_reader_unlock (GStaticRWLock* lock);
void g_static_rw_lock_writer_lock (GStaticRWLock* lock);
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);
+void g_static_rw_lock_free (GStaticRWLock* lock);
/* these are some convenience macros that expand to nothing if GLib
* was configured with --disable-threads. for using StaticMutexes,
#define THREADS 10
-static GStaticPrivate test_g_static_private_private = G_STATIC_PRIVATE_INIT;
+static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT;
+static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT;
static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT;
static guint test_g_static_private_counter = 0;
+static guint test_g_static_private_ready = 0;
static gpointer
test_g_static_private_constructor (void)
{
guint number = GPOINTER_TO_INT (data);
guint i;
- guint* private;
+ guint *private1, *private2;
for (i = 0; i < 10; i++)
{
number = number * 11 + 1; /* A very simple and bad RNG ;-) */
- private = g_static_private_get (&test_g_static_private_private);
- if (!private || number % 7 > 3)
+ private1 = g_static_private_get (&test_g_static_private_private1);
+ if (!private1 || number % 7 > 3)
{
- private = test_g_static_private_constructor ();
- g_static_private_set (&test_g_static_private_private, private,
+ private1 = test_g_static_private_constructor ();
+ g_static_private_set (&test_g_static_private_private1, private1,
test_g_static_private_destructor);
}
- *private = number;
+ *private1 = number;
+ private2 = g_static_private_get (&test_g_static_private_private2);
+ if (!private2 || number % 13 > 5)
+ {
+ private2 = test_g_static_private_constructor ();
+ g_static_private_set (&test_g_static_private_private2, private2,
+ test_g_static_private_destructor);
+ }
+ *private2 = number * 2;
+ g_usleep (G_USEC_PER_SEC / 5);
+ g_assert (number == *private1);
+ g_assert (number * 2 == *private2);
+ }
+ g_static_mutex_lock (&test_g_static_private_mutex);
+ test_g_static_private_ready++;
+ g_static_mutex_unlock (&test_g_static_private_mutex);
+
+ /* Busy wait is not nice but that's just a test */
+ while (test_g_static_private_ready != 0)
+ g_usleep (G_USEC_PER_SEC / 5);
+
+ for (i = 0; i < 10; i++)
+ {
+ private2 = g_static_private_get (&test_g_static_private_private2);
+ number = number * 11 + 1; /* A very simple and bad RNG ;-) */
+ if (!private2 || number % 13 > 5)
+ {
+ private2 = test_g_static_private_constructor ();
+ g_static_private_set (&test_g_static_private_private2, private2,
+ test_g_static_private_destructor);
+ }
+ *private2 = number * 2;
g_usleep (G_USEC_PER_SEC / 5);
- g_assert (number == *private);
+ g_assert (number * 2 == *private2);
}
}
{
GThread *threads[THREADS];
guint i;
+
+ test_g_static_private_ready = 0;
+
for (i = 0; i < THREADS; i++)
{
threads[i] = g_thread_create (test_g_static_private_thread,
0, TRUE, TRUE,
G_THREAD_PRIORITY_NORMAL, NULL);
}
+
+ /* Busy wait is not nice but that's just a test */
+ while (test_g_static_private_ready != THREADS)
+ g_usleep (G_USEC_PER_SEC / 5);
+
+ /* Reuse the static private */
+ g_static_private_free (&test_g_static_private_private2);
+ g_static_private_init (&test_g_static_private_private2);
+
+ test_g_static_private_ready = 0;
+
for (i = 0; i < THREADS; i++)
{
g_thread_join (threads[i]);
test_g_mutex ();
test_g_static_rec_mutex ();
test_g_static_private ();
- test_g_static_rw_lock ();
+ test_g_static_rw_lock ();
}
int