summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMurray Cumming <murrayc@murrayc.com>2011-11-23 13:42:55 +0100
committerMurray Cumming <murrayc@murrayc.com>2011-11-23 13:42:55 +0100
commit768123b31049e1164a50eb22af8b4c4b4fd46d72 (patch)
treee87494f4d8c73a7207b5f971673dfc21f157b627
parentd7e3bb63fa8841cf1cd06befab3a7a769adff46a (diff)
downloadglibmm-768123b31049e1164a50eb22af8b4c4b4fd46d72.tar.gz
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.
-rw-r--r--ChangeLog28
-rw-r--r--examples/network/resolver.cc4
-rw-r--r--examples/network/socket-client.cc2
-rw-r--r--examples/network/socket-server.cc2
-rw-r--r--examples/thread/dispatcher.cc4
-rw-r--r--examples/thread/dispatcher2.cc12
-rw-r--r--examples/thread/thread.cc16
-rw-r--r--examples/thread/threadpool.cc6
-rw-r--r--glib/glibmm.h2
-rw-r--r--glib/glibmm/dispatcher.cc7
-rw-r--r--glib/glibmm/exceptionhandler.cc4
-rw-r--r--glib/glibmm/main.cc15
-rw-r--r--glib/glibmm/main.h22
-rw-r--r--glib/glibmm/threadpool.cc9
-rw-r--r--glib/glibmm/threadpool.h2
-rw-r--r--glib/glibmm/utility.h6
-rw-r--r--glib/src/filelist.am2
-rw-r--r--glib/src/thread.ccg12
-rw-r--r--glib/src/thread.hg77
-rw-r--r--glib/src/threads.ccg237
-rw-r--r--glib/src/threads.hg763
21 files changed, 1163 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index e5d08848..5a84056b 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 7ce8cef9..1d6303ca 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 e6c5ae15..b1f08715 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 bc2822b1..d99a176a 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 01906ab9..7725b3ee 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 2f837b31..63b06d33 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 06c25f8c..581bdf5c 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 6ee38477..632a77af 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 7cc5ad5c..9fb35e8d 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 1be104eb..4640236c 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 79f1a81c..734da3ef 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 8bb4500f..eb279c5e 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 6d1cbda9..908b5d1f 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 acab296e..9a9af184 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 0d632f8b..9cb0f2d2 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 000e1b08..abb45357 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 fedd32b6..06c6baf9 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 bc27592a..e7d6b062 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 054667a2..a007deca 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 00000000..2431b0c0
--- /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 00000000..633189fe
--- /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