Added functions g_static_rec_mutex_init, g_static_rec_mutex_free,
authorSebastian Wilhelmi <wilhelmi@ira.uka.de>
Tue, 13 Feb 2001 15:57:44 +0000 (15:57 +0000)
committerSebastian Wilhelmi <wilhelmi@src.gnome.org>
Tue, 13 Feb 2001 15:57:44 +0000 (15:57 +0000)
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.

13 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gthread.c
glib/gthread.h
gthread.c
gthread.h
tests/thread-test.c

index 860f836..aa4b782 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 860f836..aa4b782 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 71b5627..7ec6568 100644 (file)
@@ -52,7 +52,7 @@
 #endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
 
 GQuark 
-g_thread_error_quark()
+g_thread_error_quark (void)
 {
   static GQuark quark;
   if (!quark)
@@ -117,8 +117,11 @@ GThreadFunctions g_thread_functions_for_glib_use = {
 /* 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.
@@ -137,8 +140,17 @@ g_mutex_init (void)
   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 *
@@ -152,23 +164,13 @@ g_static_mutex_get_mutex_impl (GMutex** mutex)
   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)
 {
@@ -186,6 +188,16 @@ 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)
 {
@@ -284,6 +296,19 @@ g_static_rec_mutex_unlock_full (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)
@@ -343,12 +368,23 @@ g_static_private_set_for_thread (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)
@@ -372,6 +408,35 @@ g_static_private_set_for_thread (GStaticPrivate *private_key,
     }
 }
 
+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)
 {
@@ -396,6 +461,10 @@ 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);
@@ -409,8 +478,6 @@ g_thread_fail (void)
   g_error ("The thread system is not yet initialized.");
 }
 
-G_LOCK_DEFINE_STATIC (g_thread_create);
-
 static void 
 g_thread_create_proxy (gpointer data)
 {
@@ -423,8 +490,8 @@ 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);
 }
@@ -450,11 +517,12 @@ g_thread_create (GThreadFunc               thread_func,
   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)
     {
@@ -478,6 +546,10 @@ g_thread_join (GThread* thread)
 
   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);
@@ -505,7 +577,7 @@ g_thread_set_priority (GThread* thread,
 }
 
 GThread*
-g_thread_self()
+g_thread_self (void)
 {
   GRealThread* thread = g_private_get (g_thread_specific_private);
 
@@ -526,20 +598,36 @@ g_thread_self()
       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);
@@ -547,7 +635,8 @@ static void inline g_static_rw_lock_signal (GStaticRWLock* lock)
     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);
 
@@ -561,7 +650,8 @@ void g_static_rw_lock_reader_lock (GStaticRWLock* 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;
 
@@ -580,7 +670,8 @@ gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
   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);
 
@@ -594,7 +685,8 @@ void g_static_rw_lock_reader_unlock  (GStaticRWLock* 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);
 
@@ -610,7 +702,8 @@ void g_static_rw_lock_writer_lock (GStaticRWLock* 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;
 
@@ -629,7 +722,8 @@ gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
   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);
   
@@ -642,14 +736,20 @@ void g_static_rw_lock_writer_unlock (GStaticRWLock* 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);
 }
-
index 1f86418..44145d5 100644 (file)
@@ -46,8 +46,8 @@ G_BEGIN_DECLS
 /* 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
 {
@@ -235,16 +235,18 @@ struct _GStaticPrivate
   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
@@ -255,12 +257,14 @@ 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
@@ -275,13 +279,14 @@ 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,
index 71b5627..7ec6568 100644 (file)
--- a/gthread.c
+++ b/gthread.c
@@ -52,7 +52,7 @@
 #endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
 
 GQuark 
-g_thread_error_quark()
+g_thread_error_quark (void)
 {
   static GQuark quark;
   if (!quark)
@@ -117,8 +117,11 @@ GThreadFunctions g_thread_functions_for_glib_use = {
 /* 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.
@@ -137,8 +140,17 @@ g_mutex_init (void)
   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 *
@@ -152,23 +164,13 @@ g_static_mutex_get_mutex_impl (GMutex** mutex)
   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)
 {
@@ -186,6 +188,16 @@ 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)
 {
@@ -284,6 +296,19 @@ g_static_rec_mutex_unlock_full (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)
@@ -343,12 +368,23 @@ g_static_private_set_for_thread (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)
@@ -372,6 +408,35 @@ g_static_private_set_for_thread (GStaticPrivate *private_key,
     }
 }
 
+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)
 {
@@ -396,6 +461,10 @@ 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);
@@ -409,8 +478,6 @@ g_thread_fail (void)
   g_error ("The thread system is not yet initialized.");
 }
 
-G_LOCK_DEFINE_STATIC (g_thread_create);
-
 static void 
 g_thread_create_proxy (gpointer data)
 {
@@ -423,8 +490,8 @@ 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);
 }
@@ -450,11 +517,12 @@ g_thread_create (GThreadFunc               thread_func,
   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)
     {
@@ -478,6 +546,10 @@ g_thread_join (GThread* thread)
 
   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);
@@ -505,7 +577,7 @@ g_thread_set_priority (GThread* thread,
 }
 
 GThread*
-g_thread_self()
+g_thread_self (void)
 {
   GRealThread* thread = g_private_get (g_thread_specific_private);
 
@@ -526,20 +598,36 @@ g_thread_self()
       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);
@@ -547,7 +635,8 @@ static void inline g_static_rw_lock_signal (GStaticRWLock* lock)
     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);
 
@@ -561,7 +650,8 @@ void g_static_rw_lock_reader_lock (GStaticRWLock* 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;
 
@@ -580,7 +670,8 @@ gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
   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);
 
@@ -594,7 +685,8 @@ void g_static_rw_lock_reader_unlock  (GStaticRWLock* 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);
 
@@ -610,7 +702,8 @@ void g_static_rw_lock_writer_lock (GStaticRWLock* 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;
 
@@ -629,7 +722,8 @@ gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
   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);
   
@@ -642,14 +736,20 @@ void g_static_rw_lock_writer_unlock (GStaticRWLock* 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);
 }
-
index 1f86418..44145d5 100644 (file)
--- a/gthread.h
+++ b/gthread.h
@@ -46,8 +46,8 @@ G_BEGIN_DECLS
 /* 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
 {
@@ -235,16 +235,18 @@ struct _GStaticPrivate
   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
@@ -255,12 +257,14 @@ 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
@@ -275,13 +279,14 @@ 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,
index 1fc6b83..3e689b5 100644 (file)
@@ -81,9 +81,11 @@ test_g_static_rec_mutex (void)
 
 #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)
@@ -109,20 +111,51 @@ test_g_static_private_thread (gpointer data)
 {
   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);      
     }
 }
 
@@ -131,6 +164,9 @@ test_g_static_private (void)
 {
   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, 
@@ -138,6 +174,17 @@ test_g_static_private (void)
                                    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]);
@@ -231,7 +278,7 @@ run_all_tests()
   test_g_mutex ();
   test_g_static_rec_mutex ();
   test_g_static_private ();
-  test_g_static_rw_lock ();  
+  test_g_static_rw_lock ();
 }
 
 int