[glibmm] Add Glib::Threads::* in threads.h, deprecating everything in thread.h



commit 768123b31049e1164a50eb22af8b4c4b4fd46d72
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Nov 23 13:42:55 2011 +0100

    Add Glib::Threads::* in threads.h, deprecating everything in thread.h
    
    	* glib/src/filelist.am:
    	* glib/src/thread.[hg|ccg]: Deprecate the whole file, adding
    	deprecation doxygen comments to all API.
    	* glib/src/threads.[hg|ccg]: A new Threads namespace containing
    	equivalents for everything in thread.h, implemented using
    	only non-deprecated glib API. This was necessary because we had
    	to break the ABI to do this.
    	* glib/glibmm.h: Include threads.h
    
    	* glib/glibmm/main.[h|cc]: Added a wait() method overload that
    	takes the new types, deprecating the existing wait() method.
    
    	* examples/network/resolver.cc:
    	* examples/network/socket-client.cc:
    	* examples/network/socket-server.cc:
    	* examples/thread/dispatcher.cc:
    	* examples/thread/dispatcher2.cc:
    	* examples/thread/thread.cc:
    	* examples/thread/threadpool.cc:
    	* glib/glibmm/dispatcher.cc:
    	* glib/glibmm/exceptionhandler.cc:
    	* glib/glibmm/threadpool.[h|cc]: Use the new Glib::Threads::* types
    	instead of thread.h.

 ChangeLog                         |   28 ++
 examples/network/resolver.cc      |    4 +-
 examples/network/socket-client.cc |    2 +-
 examples/network/socket-server.cc |    2 +-
 examples/thread/dispatcher.cc     |    4 +-
 examples/thread/dispatcher2.cc    |   12 +-
 examples/thread/thread.cc         |   16 +-
 examples/thread/threadpool.cc     |    6 +-
 glib/glibmm.h                     |    2 +
 glib/glibmm/dispatcher.cc         |    7 +-
 glib/glibmm/exceptionhandler.cc   |    4 +-
 glib/glibmm/main.cc               |   15 +-
 glib/glibmm/main.h                |   22 +-
 glib/glibmm/threadpool.cc         |    9 +-
 glib/glibmm/threadpool.h          |    2 +-
 glib/glibmm/utility.h             |    6 +-
 glib/src/filelist.am              |    2 +
 glib/src/thread.ccg               |   12 +-
 glib/src/thread.hg                |   77 +++-
 glib/src/threads.ccg              |  237 ++++++++++++
 glib/src/threads.hg               |  763 +++++++++++++++++++++++++++++++++++++
 21 files changed, 1163 insertions(+), 69 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e5d0884..5a84056 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,33 @@
 2011-11-23  Murray Cumming  <murrayc murrayc com>
 
+	Add Glib::Threads::* in threads.h, deprecating everything in thread.h
+
+	* glib/src/filelist.am:
+	* glib/src/thread.[hg|ccg]: Deprecate the whole file, adding 
+	deprecation doxygen comments to all API.
+	* glib/src/threads.[hg|ccg]: A new Threads namespace containing
+	equivalents for everything in thread.h, implemented using 
+	only non-deprecated glib API. This was necessary because we had
+	to break the ABI to do this.
+	* glib/glibmm.h: Include threads.h
+
+	* glib/glibmm/main.[h|cc]: Added a wait() method overload that 
+	takes the new types, deprecating the existing wait() method.
+
+	* examples/network/resolver.cc:
+	* examples/network/socket-client.cc:
+	* examples/network/socket-server.cc:
+	* examples/thread/dispatcher.cc:
+	* examples/thread/dispatcher2.cc:
+	* examples/thread/thread.cc:
+	* examples/thread/threadpool.cc:
+	* glib/glibmm/dispatcher.cc:
+	* glib/glibmm/exceptionhandler.cc:
+	* glib/glibmm/threadpool.[h|cc]: Use the new Glib::Threads::* types
+	instead of thread.h.
+
+2011-11-23  Murray Cumming  <murrayc murrayc com>
+
 	Avoid a deprecation warning in implelementation of deprecated API.
 
 	* glib/glibmm/main.cc: Define GLIB_DISABLE_DEPRECATION_WARNINGS
diff --git a/examples/network/resolver.cc b/examples/network/resolver.cc
index 7ce8cef..1d6303c 100644
--- a/examples/network/resolver.cc
+++ b/examples/network/resolver.cc
@@ -212,9 +212,11 @@ start_threaded_lookups (char **argv, int argc)
     int i;
 
     for (i = 0; i < argc; i++)
-        Glib::Thread::create (sigc::bind (sigc::ptr_fun (lookup_thread),
+    {
+        Glib::Threads::Thread::create (sigc::bind (sigc::ptr_fun (lookup_thread),
                                           argv[i]),
                               false);
+    }
 }
 
 static void
diff --git a/examples/network/socket-client.cc b/examples/network/socket-client.cc
index e6c5ae1..b1f0871 100644
--- a/examples/network/socket-client.cc
+++ b/examples/network/socket-client.cc
@@ -128,7 +128,7 @@ main (int argc,
     if (cancel_timeout)
     {
         cancellable = Gio::Cancellable::create ();
-        Glib::Thread::create (sigc::bind (sigc::ptr_fun (cancel_thread), cancellable), false);
+        Glib::Threads::Thread::create (sigc::bind (sigc::ptr_fun (cancel_thread), cancellable), false);
     }
 
     loop = Glib::MainLoop::create ();
diff --git a/examples/network/socket-server.cc b/examples/network/socket-server.cc
index bc2822b..d99a176 100644
--- a/examples/network/socket-server.cc
+++ b/examples/network/socket-server.cc
@@ -124,7 +124,7 @@ main (int argc,
     if (cancel_timeout)
     {
         cancellable = Gio::Cancellable::create ();
-        Glib::Thread::create (sigc::bind (sigc::ptr_fun (cancel_thread), cancellable), false);
+        Glib::Threads::Thread::create (sigc::bind (sigc::ptr_fun (cancel_thread), cancellable), false);
     }
 
     loop = Glib::MainLoop::create ();
diff --git a/examples/thread/dispatcher.cc b/examples/thread/dispatcher.cc
index 01906ab..7725b3e 100644
--- a/examples/thread/dispatcher.cc
+++ b/examples/thread/dispatcher.cc
@@ -45,7 +45,7 @@ private:
   // Note that the thread does not write to the member data at all.  It only
   // reads signal_increment_, which is only written to before the thread is
   // lauched.  Therefore, no locking is required.
-  Glib::Thread*       thread_;
+  Glib::Threads::Thread*       thread_;
   int                 id_;
   unsigned int        progress_;
   Glib::Dispatcher    signal_increment_;
@@ -102,7 +102,7 @@ int ThreadProgress::id() const
 void ThreadProgress::launch()
 {
   // Create a joinable thread.
-  thread_ = Glib::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true);
+  thread_ = Glib::Threads::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true);
 }
 
 void ThreadProgress::join()
diff --git a/examples/thread/dispatcher2.cc b/examples/thread/dispatcher2.cc
index 2f837b3..63b06d3 100644
--- a/examples/thread/dispatcher2.cc
+++ b/examples/thread/dispatcher2.cc
@@ -47,9 +47,9 @@ private:
   Glib::Dispatcher  signal_increment_;  
   Glib::Dispatcher* signal_finished_ptr_;
 
-  Glib::Mutex       startup_mutex_;
-  Glib::Cond        startup_cond_;
-  Glib::Thread*     thread_;
+  Glib::Threads::Mutex       startup_mutex_;
+  Glib::Threads::Cond        startup_cond_;
+  Glib::Threads::Thread*     thread_;
   
   static type_signal_end signal_end_;
 
@@ -93,10 +93,10 @@ void ThreadTimer::launch()
   // order to access the Dispatcher object instantiated by the 2nd thread.
   // So, let's do some kind of hand-shake using a mutex and a condition
   // variable.
-  Glib::Mutex::Lock lock (startup_mutex_);
+  Glib::Threads::Mutex::Lock lock (startup_mutex_);
 
   // Create a joinable thread -- it needs to be joined, otherwise it's a memory leak.
-  thread_ = Glib::Thread::create(
+  thread_ = Glib::Threads::Thread::create(
       sigc::mem_fun(*this, &ThreadTimer::thread_function), true);
 
   // Wait for the 2nd thread's startup notification.
@@ -167,7 +167,7 @@ void ThreadTimer::thread_function()
 
   // We need to lock while creating the Dispatcher instance,
   // in order to ensure memory visibility.
-  Glib::Mutex::Lock lock (startup_mutex_);
+  Glib::Threads::Mutex::Lock lock (startup_mutex_);
 
   // create a new dispatcher, that is connected to the newly
   // created MainContext
diff --git a/examples/thread/thread.cc b/examples/thread/thread.cc
index 06c25f8..581bdf5 100644
--- a/examples/thread/thread.cc
+++ b/examples/thread/thread.cc
@@ -1,7 +1,7 @@
 
 #include <iostream>
 #include <queue>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include <glibmm/random.h>
 #include <glibmm/timer.h>
 #include <glibmm/init.h>
@@ -19,9 +19,9 @@ public:
   void consumer();
 
 private:
-  Glib::Mutex     mutex_;
-  Glib::Cond      cond_push_;
-  Glib::Cond      cond_pop_;
+  Glib::Threads::Mutex mutex_;
+  Glib::Threads::Cond cond_push_;
+  Glib::Threads::Cond cond_pop_;
   std::queue<int> queue_;
 };
 
@@ -39,7 +39,7 @@ void MessageQueue::producer()
   for(int i = 0; i < 200; ++i)
   {
     {
-      Glib::Mutex::Lock lock (mutex_);
+      Glib::Threads::Mutex::Lock lock (mutex_);
 
       while(queue_.size() >= 64)
         cond_pop_.wait(mutex_);
@@ -65,7 +65,7 @@ void MessageQueue::consumer()
   for(;;)
   {
     {
-      Glib::Mutex::Lock lock (mutex_);
+      Glib::Threads::Mutex::Lock lock (mutex_);
 
       while(queue_.empty())
         cond_push_.wait(mutex_);
@@ -97,10 +97,10 @@ int main(int, char**)
 
   MessageQueue queue;
 
-  Glib::Thread *const producer = Glib::Thread::create(
+  Glib::Threads::Thread *const producer = Glib::Threads::Thread::create(
       sigc::mem_fun(queue, &MessageQueue::producer), true);
 
-  Glib::Thread *const consumer = Glib::Thread::create(
+  Glib::Threads::Thread *const consumer = Glib::Threads::Thread::create(
       sigc::mem_fun(queue, &MessageQueue::consumer), true);
 
   producer->join();
diff --git a/examples/thread/threadpool.cc b/examples/thread/threadpool.cc
index 6ee3847..632a77a 100644
--- a/examples/thread/threadpool.cc
+++ b/examples/thread/threadpool.cc
@@ -1,6 +1,6 @@
 
 #include <iostream>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include <glibmm/random.h>
 #include <glibmm/threadpool.h>
 #include <glibmm/timer.h>
@@ -9,7 +9,7 @@
 namespace
 {
 
-Glib::Mutex mutex;
+Glib::Threads::Mutex mutex;
 
 void print_char(char c)
 {
@@ -18,7 +18,7 @@ void print_char(char c)
   for(int i = 0; i < 100; ++i)
   {
     {
-      Glib::Mutex::Lock lock (mutex);
+      Glib::Threads::Mutex::Lock lock (mutex);
       std::cout << c;
       std::cout.flush();
     }
diff --git a/glib/glibmm.h b/glib/glibmm.h
index 7cc5ad5..9fb35e8 100644
--- a/glib/glibmm.h
+++ b/glib/glibmm.h
@@ -86,6 +86,8 @@
 //so we can do an undef trick to still use deprecated API in the header: 
 #include <glibmm/thread.h>
 
+#include <glibmm/threads.h>
+
 #include <glibmm/arrayhandle.h>
 #include <glibmm/balancedtree.h>
 #include <glibmm/checksum.h>
diff --git a/glib/glibmm/dispatcher.cc b/glib/glibmm/dispatcher.cc
index 1be104e..4640236 100644
--- a/glib/glibmm/dispatcher.cc
+++ b/glib/glibmm/dispatcher.cc
@@ -18,7 +18,7 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include <glibmm/dispatcher.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/fileutils.h>
@@ -137,7 +137,7 @@ protected:
   explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context);
 
 private:
-  static Glib::StaticPrivate<DispatchNotifier> thread_specific_instance_;
+  static Glib::Threads::Private<DispatchNotifier> thread_specific_instance_;
 
   long                          ref_count_;
   Glib::RefPtr<MainContext>     context_;
@@ -161,8 +161,7 @@ private:
 /**** Glib::DispatchNotifier ***********************************************/
 
 // static
-Glib::StaticPrivate<DispatchNotifier>
-DispatchNotifier::thread_specific_instance_ = GLIBMM_STATIC_PRIVATE_INIT;
+Glib::Threads::Private<DispatchNotifier> DispatchNotifier::thread_specific_instance_;
 
 DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
 :
diff --git a/glib/glibmm/exceptionhandler.cc b/glib/glibmm/exceptionhandler.cc
index 79f1a81..734da3e 100644
--- a/glib/glibmm/exceptionhandler.cc
+++ b/glib/glibmm/exceptionhandler.cc
@@ -20,7 +20,7 @@
  */
 
 #include <glibmmconfig.h>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include <glibmm/error.h>
 #include <glibmm/exceptionhandler.h>
 #include <glib.h>
@@ -35,7 +35,7 @@ typedef sigc::signal<void> HandlerList;
 
 // Each thread has its own list of exception handlers
 // to avoid thread synchronization problems.
-static Glib::StaticPrivate<HandlerList> thread_specific_handler_list = GLIBMM_STATIC_PRIVATE_INIT;
+static Glib::Threads::Private<HandlerList> thread_specific_handler_list;
 
 
 static void glibmm_exception_warning(const GError* error)
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
index 8bb4500..eb279c5 100644
--- a/glib/glibmm/main.cc
+++ b/glib/glibmm/main.cc
@@ -18,11 +18,15 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <glibmm/thread.h>
-
 #undef G_DISABLE_DEPRECATED //So we can use newly-deprecated API, to preserve our API.
 #define GLIB_DISABLE_DEPRECATION_WARNINGS 1
 
+#include <glibmm/threads.h>
+
+#ifndef GLIBMM_DISABLE_DEPRECATED
+#include <glibmm/thread.h>
+#endif //GLIBMM_DISABLE_DEPRECATED
+
 #include <glibmm/main.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/wrap.h>
@@ -492,10 +496,17 @@ bool MainContext::acquire()
   return g_main_context_acquire(gobj());
 }
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
 bool MainContext::wait(Glib::Cond& cond, Glib::Mutex& mutex)
 {
   return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj());
 }
+#endif //GLIBMM_DISABLE_DEPRECATED
+
+bool MainContext::wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex)
+{
+  return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj());
+}
 
 void MainContext::release()
 {
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h
index 6d1cbda..908b5d1 100644
--- a/glib/glibmm/main.h
+++ b/glib/glibmm/main.h
@@ -30,8 +30,16 @@
 namespace Glib
 {
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
 class Cond;
 class Mutex;
+#endif //GLIBMM_DISABLE_DEPRECATED
+
+namespace Threads
+{
+  class Cond;
+  class Mutex;
+}
 
 /** @defgroup MainLoop The Main Event Loop
  * Manages all available sources of events.
@@ -353,15 +361,27 @@ public:
    */
   bool acquire();
 
-
+#ifndef GLIBMM_DISABLE_DEPRECATED
   /** Tries to become the owner of the specified context, as with acquire(). But if another thread is the owner,
    * atomically drop mutex and wait on cond until that owner releases ownership or until cond is signaled, then try
    * again (once) to become the owner.
    * @param cond A condition variable.
    * @param mutex A mutex, currently held.
    * @return true if the operation succeeded, and this thread is now the owner of context.
+   *
+   * @deprecated Use wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex) instead.
    */
   bool wait(Glib::Cond& cond, Glib::Mutex& mutex);
+#endif //GLIBMM_DISABLE_DEPRECATED
+
+  /** Tries to become the owner of the specified context, as with acquire(). But if another thread is the owner,
+   * atomically drop mutex and wait on cond until that owner releases ownership or until cond is signaled, then try
+   * again (once) to become the owner.
+   * @param cond A condition variable.
+   * @param mutex A mutex, currently held.
+   * @return true if the operation succeeded, and this thread is now the owner of context.
+   */
+  bool wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex);
 
   /** Releases ownership of a context previously acquired by this thread with acquire(). If the context was acquired
    * multiple times, the only release ownership when release() is called as many times as it was acquired.
diff --git a/glib/glibmm/threadpool.cc b/glib/glibmm/threadpool.cc
index acab296..9a9af18 100644
--- a/glib/glibmm/threadpool.cc
+++ b/glib/glibmm/threadpool.cc
@@ -20,6 +20,7 @@
 #include <glibmmconfig.h>
 #include <glibmm/threadpool.h>
 #include <glibmm/exceptionhandler.h>
+#include <glibmm/threads.h>
 #include <glib.h>
 #include <list>
 
@@ -39,7 +40,7 @@ public:
   void lock_and_unlock();
 
 private:
-  Glib::Mutex                     mutex_;
+  Glib::Threads::Mutex                     mutex_;
   std::list< sigc::slot<void> >  list_;
 
   // noncopyable
@@ -55,7 +56,7 @@ ThreadPool::SlotList::~SlotList()
 
 sigc::slot<void>* ThreadPool::SlotList::push(const sigc::slot<void>& slot)
 {
-  Mutex::Lock lock (mutex_);
+  Threads::Mutex::Lock lock (mutex_);
 
   list_.push_back(slot);
   return &list_.back();
@@ -66,7 +67,7 @@ sigc::slot<void> ThreadPool::SlotList::pop(sigc::slot<void>* slot_ptr)
   sigc::slot<void> slot;
 
   {
-    Mutex::Lock lock (mutex_);
+    Threads::Mutex::Lock lock (mutex_);
 
     std::list< sigc::slot<void> >::iterator pslot = list_.begin();
     while(pslot != list_.end() && slot_ptr != &*pslot)
@@ -105,7 +106,7 @@ static void call_thread_entry_slot(void* data, void* user_data)
 
     slot();
   }
-  catch(Glib::Thread::Exit&)
+  catch(Glib::Threads::Thread::Exit&)
   {
     // Just exit from the thread.  The Thread::Exit exception
     // is our sane C++ replacement of g_thread_exit().
diff --git a/glib/glibmm/threadpool.h b/glib/glibmm/threadpool.h
index 0d632f8..9cb0f2d 100644
--- a/glib/glibmm/threadpool.h
+++ b/glib/glibmm/threadpool.h
@@ -21,7 +21,7 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <glibmm/thread.h>
+#include <sigc++/sigc++.h>
 
 extern "C" { typedef struct _GThreadPool GThreadPool; }
 
diff --git a/glib/glibmm/utility.h b/glib/glibmm/utility.h
index 000e1b0..abb4535 100644
--- a/glib/glibmm/utility.h
+++ b/glib/glibmm/utility.h
@@ -30,19 +30,21 @@
  * GLIBMM_INITIALIZE_STRUCT(Var, Type) is provided.  It even avoids creating
  * a temporary if the compiler is GCC.
  */
-#if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__)
+#if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
 
 #define GLIBMM_INITIALIZE_STRUCT(Var, Type) __builtin_memset(&(Var), 0, sizeof(Type))
 
 #else
 
+//TODO: This causes warnings like this:
+//"missing initializer for member"
 #define GLIBMM_INITIALIZE_STRUCT(Var, Type) \
     G_STMT_START{ \
         Type const temp_initializer__ = { 0, }; \
         (Var) = temp_initializer__; \
     }G_STMT_END
 
-#endif /* ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__) */
+#endif
 
 
 namespace Glib
diff --git a/glib/src/filelist.am b/glib/src/filelist.am
index fedd32b..06c6baf 100644
--- a/glib/src/filelist.am
+++ b/glib/src/filelist.am
@@ -14,6 +14,7 @@ glibmm_files_defs =		\
 	glib_docs.xml		\
 	glib_docs_override.xml
 
+# Note that all of thread.hg is deprecated 
 glibmm_files_hg =		\
 	balancedtree.hg		\
 	checksum.hg		\
@@ -33,6 +34,7 @@ glibmm_files_hg =		\
 	shell.hg		\
 	spawn.hg		\
 	thread.hg		\
+	threads.hg		\
 	timezone.hg		\
 	unicode.hg		\
 	uriutils.hg		\
diff --git a/glib/src/thread.ccg b/glib/src/thread.ccg
index bc27592..e7d6b06 100644
--- a/glib/src/thread.ccg
+++ b/glib/src/thread.ccg
@@ -21,6 +21,7 @@
 #include <glibmm/exceptionhandler.h>
 #include <glib.h>
 
+_DEPRECATE_IFDEF_START
 
 namespace
 {
@@ -59,8 +60,6 @@ static void* call_thread_entry_slot(void* data)
 namespace Glib
 {
 
-_DEPRECATE_IFDEF_START
-
 // This was always meant as an internal method. It is no longer called,
 // and no longer needs to be called. We are keeping it just to avoid 
 // breaking ABI, though hopefully nobody is using it anyway.
@@ -71,8 +70,6 @@ void thread_init_impl()
   Glib::Error::register_init();
 }
 
-_DEPRECATE_IFDEF_END
-
 /**** Glib::Thread *********************************************************/
 
 // static
@@ -87,7 +84,6 @@ Thread* Thread::create(const sigc::slot<void>& slot, bool /* joinable */)
   return reinterpret_cast<Thread*>(thread);
 }
 
-_DEPRECATE_IFDEF_START
 // static
 Thread* Thread::create(const sigc::slot<void>& slot, unsigned long stack_size,
                        bool joinable, bool bound, ThreadPriority priority)
@@ -109,7 +105,6 @@ Thread* Thread::create(const sigc::slot<void>& slot, unsigned long stack_size,
 
   return reinterpret_cast<Thread*>(thread);
 }
-_DEPRECATE_IFDEF_END
 
 // static
 Thread* Thread::self()
@@ -122,8 +117,6 @@ void Thread::join()
   g_thread_join(&gobject_);
 }
 
-_DEPRECATE_IFDEF_START
-
 bool Thread::joinable() const
 {
   return true; //An appropriate result now that this is deprecated because all threads are now joinable.
@@ -155,8 +148,6 @@ bool thread_supported()
   return (g_thread_supported() != 0);
 }
 
-_DEPRECATE_IFDEF_END
-
 
 // static
 void Thread::yield()
@@ -387,3 +378,4 @@ bool Cond::timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time)
 
 } // namespace Glib
 
+_DEPRECATE_IFDEF_END
diff --git a/glib/src/thread.hg b/glib/src/thread.hg
index 054667a..a007dec 100644
--- a/glib/src/thread.hg
+++ b/glib/src/thread.hg
@@ -19,6 +19,8 @@ _DEFS(glibmm,glib)
 
 #include <glibmmconfig.h>
 
+_DEPRECATE_IFDEF_START
+
 // We use GThreadFunctions in the (deprecated) API, so we must temporarily undef G_DISABLE_DEPRECATED.
 // Temporarily undef G_DISABLE_DEPRECATED, redefining it later if appropriate.
 #if defined(G_DISABLE_DEPRECATED) && !defined(GLIBMM_G_DISABLE_DEPRECATED_UNDEFED)
@@ -63,27 +65,30 @@ enum { THREAD_PRIORITY_NORMAL = GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL }
 /** Initializer macro for Glib::StaticRecMutex.
  * @relates Glib::StaticRecMutex
  * @hideinitializer
+ *
+ * @deprecated Glib::StaticRecMutex is deprecated in favour of Glib::Threads::RecMutex, which can be used statically. 
  */
 #define GLIBMM_STATIC_REC_MUTEX_INIT { G_STATIC_REC_MUTEX_INIT }
 
 /** Initializer macro for Glib::StaticRWLock.
  * @relates Glib::StaticRWLock
  * @hideinitializer
+ *
+ * @deprecated Glib::StaticRWLock is deprecated in favour of Glib::Threads::RWLock, which can be used statically. 
  */
 #define GLIBMM_STATIC_RW_LOCK_INIT { G_STATIC_RW_LOCK_INIT }
 
 /** Initializer macro for Glib::StaticPrivate.
  * @relates Glib::StaticPrivate
  * @hideinitializer
+ *
+ * @deprecated Glib::StaticPrivate is deprecated in favour of Glib::Threads::Private, which can be used statically. 
  */
 #define GLIBMM_STATIC_PRIVATE_INIT { G_STATIC_PRIVATE_INIT }
 
 namespace Glib
 {
 
-
-_DEPRECATE_IFDEF_START
-
 /** @deprecated Thread priorities no longer have any effect.
  */
 _WRAP_ENUM(ThreadPriority, GThreadPriority, NO_GTYPE)
@@ -112,15 +117,14 @@ void thread_init(GThreadFunctions* vtable = 0);
  */
 bool thread_supported();
 
-_DEPRECATE_IFDEF_END
-
-/** @defgroup Threads Threads
- * Thread abstraction; including threads, different mutexes,
- * conditions and thread private data.
- * @{
+/**
+ * @deprecated Use Glib::Threads::NotLock instead.
  */
-
 enum NotLock { NOT_LOCK };
+
+/**
+ * @deprecated Use Glib::Threads::TryLock instead.
+ */
 enum TryLock { TRY_LOCK };
 
 class Mutex;
@@ -132,6 +136,7 @@ struct StaticRWLock;
 
 
 /** Exception class for thread-related errors.
+ * @deprecated Use Glib::Threads::ThreadError instead.
  */
 _WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
 
@@ -152,6 +157,8 @@ _WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
  * @note You might have noticed that the thread entry slot doesn't have the
  * usual void* return value.  If you want to return any data from your thread
  * you can pass an additional output argument to the thread's entry slot.
+ *
+ * @deprecated Use Glib::Threads::Thread instead.
  */
 class Thread
 {
@@ -192,7 +199,6 @@ public:
    */
   void join();
 
-_DEPRECATE_IFDEF_START
   //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
   /** Creates a new thread with the priority @a priority. The stack gets the
    * size @a stack_size or the default value for the current platform, if
@@ -268,8 +274,6 @@ _DEPRECATE_IFDEF_START
    */
   ThreadPriority get_priority() const;
 
-_DEPRECATE_IFDEF_END
-
   /** 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.
@@ -299,15 +303,20 @@ private:
  * Write this if you want to exit from a thread created by Thread::create().
  * Of course you must make sure not to catch Thread::Exit by accident, i.e.
  * when using <tt>catch(...)</tt> somewhere in your code.
+ *
+ * @deprecated Use Glib::Threads::Thread::Exit instead.
  */
 class Thread::Exit
 {};
 
-/** @relates Glib::Thread */
-Thread* wrap(GThread* gobject);
 
+//TODO: Make sure that Glib::wrap() uses Glib::Threads::wrap() instead.
 
-_DEPRECATE_IFDEF_START
+/** @relates Glib::Thread
+ *
+ * @deprecated Use Glib::Threads::wrap(GThread*) instead.
+ */
+Thread* wrap(GThread* gobject);
 
 struct StaticMutex;
 
@@ -321,6 +330,8 @@ struct StaticMutex;
  * silently do nothing then.  That will also work when using the implicit
  * conversion to Mutex&, thus you can safely use Mutex::Lock with a
  * StaticMutex.
+ *
+ * @deprecated Use Glib::Threads::Mutex instead, which can be used statically. 
  */
 struct StaticMutex
 {
@@ -341,11 +352,11 @@ struct StaticMutex
 /** Initializer macro for Glib::StaticMutex.
  * @relates Glib::StaticMutex
  * @hideinitializer
+ *
+ * @deprecated  Glib::StaticMutex is deprecated in favour of Glib::Threads::Mutex, which can be used statically. 
  */
 #define GLIBMM_STATIC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
 
-_DEPRECATE_IFDEF_END
-
 /** Represents a mutex (mutual exclusion).
  * It can be used to protect data against shared access.  Try to use
  * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
@@ -354,6 +365,8 @@ _DEPRECATE_IFDEF_END
  * @note Glib::Mutex is not recursive, i.e. a thread will deadlock, if it
  * already has locked the mutex while calling lock().  Use Glib::RecMutex
  * instead, if you need recursive mutexes.
+ *
+ * @deprecated Use Glib::Threads::Mutex instead.
  */
 class Mutex
 {
@@ -407,6 +420,8 @@ private:
  * only exception safe but also much less error-prone.  You could even
  * <tt>return</tt> while still holding the lock and it will be released
  * properly.
+ *
+ * @deprecated Use Glib::Threads::Mutex::Lock instead.
  */
 class Mutex::Lock
 {
@@ -440,6 +455,8 @@ private:
  * silently do nothing then.  That will also work when using the implicit
  * conversion to RecMutex&, thus you can safely use RecMutex::Lock with a
  * StaticRecMutex.
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead, which can be used statically.
  */
 struct StaticRecMutex
 {
@@ -460,6 +477,10 @@ struct StaticRecMutex
 #endif
 };
 
+/**
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead.
+ */
 class RecMutex : public StaticRecMutex
 {
 public:
@@ -475,6 +496,8 @@ private:
 };
 
 /** Utility class for exception-safe locking of recursive mutexes.
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead.
  */
 class RecMutex::Lock
 {
@@ -508,6 +531,8 @@ private:
  * silently do nothing then.  That will also work when using the implicit
  * conversion to RWLock&, thus you can safely use RWLock::ReaderLock and
  * RWLock::WriterLock with a StaticRWLock.
+ *
+ * @deprecated Use Glib::Threads::RWLock instead, which can be used statically.
  */
 struct StaticRWLock
 {
@@ -529,6 +554,10 @@ struct StaticRWLock
 #endif
 };
 
+/**
+ *
+ * @deprecated Use Glib::Threads::RWLock instead.
+ */
 class RWLock : public StaticRWLock
 {
 public:
@@ -545,6 +574,8 @@ private:
 };
 
 /** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Use Glib::Threads::RWLock::ReaderLock instead.
  */
 class RWLock::ReaderLock
 {
@@ -569,6 +600,8 @@ private:
 };
 
 /** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Use Glib::Threads::RWLock::WriterLock instead.
  */
 class RWLock::WriterLock
 {
@@ -623,7 +656,9 @@ private:
  *   return data;
  * }
  * @endcode
-*/
+ *
+ * @deprecated Use Glib::Threads::Cond instead.
+ */
 class Cond
 {
 public:
@@ -736,12 +771,10 @@ private:
 /*  inline implementation                                                  */
 /***************************************************************************/
 
-_DEPRECATE_IFDEF_START
 // internal
 /** @deprecated This was always for internal glibmm use and is now unecessary even inside glibmm.
  */
 void thread_init_impl();
-_DEPRECATE_IFDEF_END
 
 /**** Glib::Mutex::Lock ****************************************************/
 
@@ -1038,3 +1071,5 @@ void Private<T>::set(T* data)
 _IGNORE(g_iconv)
 
 } // namespace Glib
+
+_DEPRECATE_IFDEF_END
diff --git a/glib/src/threads.ccg b/glib/src/threads.ccg
new file mode 100644
index 0000000..2431b0c
--- /dev/null
+++ b/glib/src/threads.ccg
@@ -0,0 +1,237 @@
+// -*- c++ -*-
+/* $Id: thread.ccg,v 1.9 2006/05/12 08:08:44 murrayc Exp $ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+#include <glib.h>
+
+
+namespace
+{
+
+extern "C"
+{
+
+static void* call_thread_entry_slot(void* data)
+{
+  sigc::slot_base *const slot = reinterpret_cast<sigc::slot_base*>(data);
+
+  try
+  {
+    // Recreate the specific slot, and drop the reference obtained by create().
+    (*static_cast<sigc::slot<void>*>(slot))();
+  }
+  catch(Glib::Thread::Exit&)
+  {
+    // Just exit from the thread.  The Thread::Exit exception
+    // is our sane C++ replacement of g_thread_exit().
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  delete slot;
+  return 0;
+}
+
+} //extern "C"
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+namespace Threads
+{
+
+/**** Glib::Thread *********************************************************/
+
+// static
+Thread* Thread::create(const sigc::slot<void>& slot, bool /* joinable */)
+{
+  // Make a copy of slot on the heap
+  sigc::slot_base *const slot_copy = new sigc::slot<void>(slot);
+
+  GThread *const thread = g_thread_new(NULL, 
+      &call_thread_entry_slot, slot_copy);
+
+  return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread* Thread::self()
+{
+  return reinterpret_cast<Thread*>(g_thread_self());
+}
+
+void Thread::join()
+{
+  g_thread_join(&gobject_);
+}
+
+// static
+void Thread::yield()
+{
+  g_thread_yield();
+}
+
+
+Thread* wrap(GThread* gobject)
+{
+  return reinterpret_cast<Thread*>(gobject);
+}
+
+
+/**** Glib::Mutex **********************************************************/
+
+Mutex::Mutex()
+{
+  g_mutex_init(&gobject_);
+}
+
+Mutex::~Mutex()
+{
+  g_mutex_clear(&gobject_);
+}
+
+void Mutex::lock()
+{
+  g_mutex_lock(&gobject_);
+}
+
+bool Mutex::trylock()
+{
+  return g_mutex_trylock(&gobject_);
+}
+
+void Mutex::unlock()
+{
+  g_mutex_unlock(&gobject_);
+}
+
+/**** Glib::RecMutex *******************************************************/
+
+RecMutex::RecMutex()
+{
+  g_rec_mutex_init(&gobject_);
+}
+
+RecMutex::~RecMutex()
+{
+  g_rec_mutex_clear(&gobject_);
+}
+
+void RecMutex::lock()
+{
+  g_rec_mutex_lock(&gobject_);
+}
+
+bool RecMutex::trylock()
+{
+  return g_rec_mutex_trylock(&gobject_);
+}
+
+void RecMutex::unlock()
+{
+  g_rec_mutex_unlock(&gobject_);
+}
+
+/**** Glib::RWLock ***************************************************/
+
+void RWLock::reader_lock()
+{
+  g_rw_lock_reader_lock(&gobject_);
+}
+
+bool RWLock::reader_trylock()
+{
+  return g_rw_lock_reader_trylock(&gobject_);
+}
+
+void RWLock::reader_unlock()
+{
+  g_rw_lock_reader_unlock(&gobject_);
+}
+
+void RWLock::writer_lock()
+{
+  g_rw_lock_writer_lock(&gobject_);
+}
+
+bool RWLock::writer_trylock()
+{
+  return g_rw_lock_writer_trylock(&gobject_);
+}
+
+void RWLock::writer_unlock()
+{
+  g_rw_lock_writer_unlock(&gobject_);
+}
+
+/**** Glib::RWLock *********************************************************/
+
+RWLock::RWLock()
+{
+  g_rw_lock_init(&gobject_);
+}
+
+RWLock::~RWLock()
+{
+  g_rw_lock_clear(&gobject_);
+}
+
+
+/**** Glib::Cond ***********************************************************/
+
+Cond::Cond()
+{
+  g_cond_init(&gobject_);
+}
+
+Cond::~Cond()
+{
+  g_cond_clear(&gobject_);
+}
+
+void Cond::signal()
+{
+  g_cond_signal(&gobject_);
+}
+
+void Cond::broadcast()
+{
+  g_cond_broadcast(&gobject_);
+}
+
+void Cond::wait(Mutex& mutex)
+{
+  g_cond_wait(&gobject_, mutex.gobj());
+}
+
+bool Cond::wait_until(Mutex& mutex, gint64 end_time)
+{
+  return g_cond_wait_until(&gobject_, mutex.gobj(), end_time);
+}
+
+} // namespace Threads
+
+} // namespace Glib
+
diff --git a/glib/src/threads.hg b/glib/src/threads.hg
new file mode 100644
index 0000000..633189f
--- /dev/null
+++ b/glib/src/threads.hg
@@ -0,0 +1,763 @@
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glibmmconfig.h>
+
+#include <glib.h>
+
+#include <glibmm/error.h>
+#include <sigc++/sigc++.h>
+
+#include <cstddef>
+
+namespace Glib
+{
+
+namespace Threads
+{
+
+/** @defgroup Threads Threads
+ * Thread abstraction; including threads, different mutexes,
+ * conditions and thread private data.
+ * @{
+ */
+
+enum NotLock { NOT_LOCK };
+enum TryLock { TRY_LOCK };
+
+class Mutex;
+class RecMutex;
+class RWLock;
+
+/** Exception class for thread-related errors.
+ */
+_WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
+
+
+/** Represents a running thread.
+ * An instance of this class can only be obtained with create(), self(),
+ * or wrap(GThread*).  It's not possible to delete a Thread object.  If the
+ * thread is @em not joinable, its resources will be freed automatically
+ * when it exits.  Otherwise, if the thread @em is joinable, you must call
+ * join() to avoid a memory leak.
+ *
+ * @note g_thread_exit() is not wrapped, because that function exits a thread
+ * without any cleanup.  That's especially dangerous in C++ code, since the
+ * destructors of automatic objects won't be invoked.  Instead, you can throw
+ * a Thread::Exit exception, which will be caught by the internal thread
+ * entry function.
+ *
+ * @note You might have noticed that the thread entry slot doesn't have the
+ * usual void* return value.  If you want to return any data from your thread
+ * you can pass an additional output argument to the thread's entry slot.
+ */
+class Thread
+{
+public:
+  class Exit;
+
+  //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+  /** Creates a new thread with the priority <tt>THREAD_PRIORITY_NORMAL</tt>.
+   * If @a joinable is @c true, you can wait for this thread's termination by
+   * calling join().  Otherwise the thread will just disappear, when ready.
+   *
+   * The new thread executes the function or method @a slot points to.  You can
+   * pass additional arguments using sigc::bind().  If the thread was created
+   * successfully, it is returned, otherwise a ThreadError exception is thrown.
+   *
+   * Because sigc::trackable is not thread safe, if the slot represents a
+   * non-static class method (that is, it is created by sigc::mem_fun()), the
+   * class concerned should not derive from sigc::trackable.
+   *
+   * @param slot A slot to execute in the new thread.
+   * @param joinable This parameter is now ignored because Threads are now always joinable.
+   * @return The new Thread* on success.
+   * @throw Glib::ThreadError
+   */
+  static Thread* create(const sigc::slot<void>& slot, bool joinable = true);
+
+  /** Returns the Thread* corresponding to the calling thread.
+   * @return The current thread.
+   */
+  static Thread* self();
+
+  /** Waits until the thread finishes.
+   * Waits until the thread finishes, i.e. the slot, as given to create(),
+   * returns or g_thread_exit() is called by the thread.  (Calling
+   * g_thread_exit() in a C++ program should be avoided.)  All resources of
+   * the thread including the Glib::Thread object are released.  The thread
+   * must have been created with <tt>joinable&nbsp;=&nbsp;true</tt>.
+   */
+  void join();
+
+  /** 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.
+   */
+  static void yield();
+
+  GThread*       gobj()       { return &gobject_; }
+  const GThread* gobj() const { return &gobject_; }
+
+private:
+  GThread gobject_;
+
+  // Glib::Thread can neither be constructed nor deleted.
+  Thread();
+  void operator delete(void*, size_t);
+
+  // noncopyable
+  Thread(const Thread&);
+  Thread& operator=(const Thread&);
+};
+
+/** %Exception class used to exit from a thread.
+ * @code
+ * throw Glib::Thread::Exit();
+ * @endcode
+ * Write this if you want to exit from a thread created by Thread::create().
+ * Of course you must make sure not to catch Thread::Exit by accident, i.e.
+ * when using <tt>catch(...)</tt> somewhere in your code.
+ */
+class Thread::Exit
+{};
+
+/** @relates Glib::Thread */
+Thread* wrap(GThread* gobject);
+
+/** Represents a mutex (mutual exclusion).
+ * It can be used to protect data against shared access.  Try to use
+ * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
+ * it will make your life much easier.
+ *
+ * @note Glib::Mutex is not recursive, i.e. a thread will deadlock, if it
+ * already has locked the mutex while calling lock().  Use Glib::RecMutex
+ * instead, if you need recursive mutexes.
+ */
+class Mutex
+{
+public:
+  class Lock;
+
+  Mutex();
+  ~Mutex();
+
+  /** Locks the mutex.
+   * If mutex is already locked by another thread, the current thread will
+   * block until mutex is unlocked by the other thread.
+   * @see Mutex::Lock
+   */
+  void lock();
+
+  /** Tries to lock the mutex.
+   * If the mutex is already locked by another thread, it immediately returns
+   * @c false.  Otherwise it locks the mutex and returns @c true.
+   * @return Whether the mutex could be locked.
+   * @see Mutex::Lock
+   */
+  bool trylock();
+
+  /** Unlocks the mutex.
+   * If another thread is blocked in a lock() call for this mutex, it will be
+   * woken and can lock the mutex itself.
+   * @see Mutex::Lock
+   */
+  void unlock();
+
+  GMutex* gobj() { return &gobject_; }
+
+private:
+  GMutex gobject_;
+
+  // noncopyable
+  Mutex(const Mutex&);
+  Mutex& operator=(const Mutex&);
+};
+
+/** Utility class for exception-safe mutex locking.
+ * @par Usage example:
+ * @code
+ * {
+ *   Glib::Mutex::Lock lock (mutex); // calls mutex.lock()
+ *   do_something();
+ * } // the destructor calls mutex.unlock()
+ * @endcode
+ * As you can see, the compiler takes care of the unlocking.  This is not
+ * only exception safe but also much less error-prone.  You could even
+ * <tt>return</tt> while still holding the lock and it will be released
+ * properly.
+ */
+class Mutex::Lock
+{
+public:
+  explicit inline Lock(Mutex& mutex);
+  inline Lock(Mutex& mutex, NotLock);
+  inline Lock(Mutex& mutex, TryLock);
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  Mutex&  mutex_;
+  bool    locked_;
+
+  // noncopyable
+  Lock(const Mutex::Lock&);
+  Mutex::Lock& operator=(const Mutex::Lock&);
+};
+
+//TODO: Docuemenation
+class RecMutex
+{
+public:
+  class Lock;
+
+  RecMutex();
+  ~RecMutex();
+
+  void lock();
+  bool trylock();
+  void unlock();
+
+  GRecMutex* gobj() { return &gobject_; }
+
+private:
+  // noncopyable
+  RecMutex(const RecMutex&);
+  RecMutex& operator=(const RecMutex&);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GRecMutex gobject_;
+#endif
+};
+
+/** Utility class for exception-safe locking of recursive mutexes.
+ */
+class RecMutex::Lock
+{
+public:
+  explicit inline Lock(RecMutex& mutex);
+  inline Lock(RecMutex& mutex, NotLock);
+  inline Lock(RecMutex& mutex, TryLock);
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RecMutex& mutex_;
+  bool      locked_;
+
+  // noncopyable
+  Lock(const RecMutex::Lock&);
+  RecMutex::Lock& operator=(const RecMutex::Lock&);
+};
+
+
+//TODO: Documentation
+class RWLock
+{
+public:
+  class ReaderLock;
+  class WriterLock;
+
+  RWLock();
+  ~RWLock();
+
+  void reader_lock();
+  bool reader_trylock();
+  void reader_unlock();
+
+  void writer_lock();
+  bool writer_trylock();
+  void writer_unlock();
+
+  GRWLock* gobj() { return &gobject_; }
+
+private:
+  // noncopyable
+  RWLock(const RWLock&);
+  RWLock& operator=(const RWLock&);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GRWLock gobject_;
+#endif
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ */
+class RWLock::ReaderLock
+{
+public:
+  explicit inline ReaderLock(RWLock& rwlock);
+  inline ReaderLock(RWLock& rwlock, NotLock);
+  inline ReaderLock(RWLock& rwlock, TryLock);
+  inline ~ReaderLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+
+  // noncopyable
+  ReaderLock(const RWLock::ReaderLock&);
+  RWLock::ReaderLock& operator=(const RWLock::ReaderLock&);
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ */
+class RWLock::WriterLock
+{
+public:
+  explicit inline WriterLock(RWLock& rwlock);
+  inline WriterLock(RWLock& rwlock, NotLock);
+  inline WriterLock(RWLock& rwlock, TryLock);
+  inline ~WriterLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+
+  // noncopyable
+  WriterLock(const RWLock::WriterLock&);
+  RWLock::WriterLock& operator=(const RWLock::WriterLock&);
+};
+
+/** An opaque data structure to represent a condition. 
+ * A @a Cond is an object that threads can block on, if they find a certain 
+ * condition to be false. If other threads change the state of this condition 
+ * they can signal the @a Cond, such that the waiting thread is woken up.
+ * @par Usage example:
+ * @code
+ * Glib::Cond  data_cond;
+ * Glib::Mutex data_mutex;
+ * void* current_data = 0;
+ *
+ * void push_data(void* data)
+ * {
+ *   Glib::Mutex::Lock lock (data_mutex);
+ *
+ *   current_data = data;
+ *   data_cond.signal();
+ * }
+ *
+ * void* pop_data()
+ * {
+ *   Glib::Mutex::Lock lock (data_mutex);
+ *
+ *   while (!current_data)
+ *     data_cond.wait(data_mutex);
+ *
+ *   void *const data = current_data;
+ *   current_data = 0;
+ *
+ *   return data;
+ * }
+ * @endcode
+*/
+class Cond
+{
+public:
+  Cond();
+  ~Cond();
+
+  /** If threads are waiting for this @a Cond, exactly one of them is woken up. 
+   * It is good practice to hold the same lock as the waiting thread, while calling 
+   * this method, though not required.
+   *
+   */
+  void signal();
+
+  /** If threads are waiting for this @a Cond, all of them are woken up.
+   * It is good practice to hold the same lock as the waiting thread, while calling 
+   * this method, though not required.
+   */
+  void broadcast();
+
+  /** Waits until this thread is woken up on this @a Cond.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @param mutex a @a Mutex that is currently locked.
+   * 
+   * @note It is important to use the @a wait() and @a wait_until() methods
+   * only inside a loop, which checks for the condition to be true as it is not 
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling 
+   * thread left the condition in that state. This is because another thread can have 
+   * altered the condition, before the waiting thread got the chance to be woken up, 
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  void wait(Mutex& mutex);
+
+  /** Waits until this thread is woken up on this @a Cond, but not longer than until the time, that is specified by @a abs_time.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @param mutex a @a Mutex that is currently locked.
+   * @param abs_time a max time to wait.
+   * 
+   * @note It is important to use the @a wait() and @a wait_until() methods
+   * only inside a loop, which checks for the condition to be true as it is not 
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling 
+   * thread left the condition in that state. This is because another thread can have 
+   * altered the condition, before the waiting thread got the chance to be woken up, 
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  bool wait_until(Mutex& mutex, gint64 end_time);
+
+  GCond* gobj() { return &gobject_; }
+
+private:
+  GCond gobject_;
+
+  // noncopyable
+  Cond(const Cond&);
+  Cond& operator=(const Cond&);
+};
+
+template <class T>
+class Private
+{
+public:
+  typedef void (*DestructorFunc) (void*);
+
+  static void delete_ptr(void* data);
+
+  explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
+  inline T* get();
+  inline void set(T* data);
+
+  GPrivate* gobj() { return gobject_; }
+
+private:
+  GPrivate gobject_;
+
+  // noncopyable
+  Private(const Private<T>&);
+  Private<T>& operator=(const Private<T>&);
+};
+
+/** @} group Threads */
+
+/*! A glibmm thread example.
+ * @example thread/thread.cc
+ */
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/***************************************************************************/
+/*  inline implementation                                                  */
+/***************************************************************************/
+
+
+/**** Glib::Mutex::Lock ****************************************************/
+
+inline
+Mutex::Lock::Lock(Mutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+Mutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void Mutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool Mutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void Mutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool Mutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RecMutex::Lock *************************************************/
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+RecMutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void RecMutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool RecMutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void RecMutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool RecMutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RWLock::ReaderLock *********************************************/
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.reader_lock();
+}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.reader_trylock())
+{}
+
+inline
+RWLock::ReaderLock::~ReaderLock()
+{
+  if(locked_)
+    rwlock_.reader_unlock();
+}
+
+inline
+void RWLock::ReaderLock::acquire()
+{
+  rwlock_.reader_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::ReaderLock::try_acquire()
+{
+  locked_ = rwlock_.reader_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::ReaderLock::release()
+{
+  rwlock_.reader_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::ReaderLock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RWLock::WriterLock *********************************************/
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.writer_lock();
+}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.writer_trylock())
+{}
+
+inline
+RWLock::WriterLock::~WriterLock()
+{
+  if(locked_)
+    rwlock_.writer_unlock();
+}
+
+inline
+void RWLock::WriterLock::acquire()
+{
+  rwlock_.writer_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::WriterLock::try_acquire()
+{
+  locked_ = rwlock_.writer_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::WriterLock::release()
+{
+  rwlock_.writer_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::WriterLock::locked() const
+{
+  return locked_;
+}
+
+/**** Glib::Private ********************************************************/
+
+// static
+template <class T>
+void Private<T>::delete_ptr(void* data)
+{
+  delete static_cast<T*>(data);
+}
+
+template <class T> inline
+Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
+{
+  //TODO: This causes this warning:
+  //extended initializer lists only available with -std=c++0x or -std=gnu++0x
+  //See glib bug: https://bugzilla.gnome.org/show_bug.cgi?id=664618
+  //We can work around this by building like so:
+  //./configure --prefix=/opt/gnome30 'CXXFLAGS=-std=c++0x'
+  gobject_ = G_PRIVATE_INIT(destructor_func);
+}
+
+template <class T> inline
+T* Private<T>::get()
+{
+  return static_cast<T*>(g_private_get(&gobject_));
+}
+
+template <class T> inline
+void Private<T>::set(T* data)
+{
+  g_private_set(&gobject_, data);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+// For some reason gmmproc thinks that g_iconv should be wrapped here.
+_IGNORE(g_iconv)
+
+} //namespace Threads
+
+} // namespace Glib



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]