summaryrefslogtreecommitdiff
path: root/glib/src/threads.hg
diff options
context:
space:
mode:
Diffstat (limited to 'glib/src/threads.hg')
-rw-r--r--glib/src/threads.hg141
1 files changed, 72 insertions, 69 deletions
diff --git a/glib/src/threads.hg b/glib/src/threads.hg
index 52bb4b41..412d5fb5 100644
--- a/glib/src/threads.hg
+++ b/glib/src/threads.hg
@@ -18,39 +18,17 @@
_DEFS(glibmm,glib)
_CONFIGINCLUDE(glibmmconfig.h)
-
-// We use the (now deprecated) GThread definition in the API,
-// and we cannot stop that without breaking ABI.
-// (see the comment below),
-// so we must temporarily undef G_DISABLE_DEPRECATED when
-// including glib.h.
-
-// Temporarily undef G_DISABLE_DEPRECATED, redefining it later if appropriate.
-#if defined(G_DISABLE_DEPRECATED) && !defined(GLIBMM_G_DISABLE_DEPRECATED_UNDEFED)
-
-//Stop the deprecation ifdef guards around the API declarations:
-#undef G_DISABLE_DEPRECATED
-
-//Stop the compiler warnings about using the deprecated API;
-#define GLIB_DISABLE_DEPRECATION_WARNINGS 1
-
-#define GLIBMM_G_DISABLE_DEPRECATED_UNDEFED 1
-
-#endif
+#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
+// Don't let glibmm.h include thread.h. Pretend that it's already included.
+// glib.h can then be included with G_DISABLE_DEPRECATED defined, and
+// the compiler can react if deprecated glib functions are used.
+#define _GLIBMM_THREAD_H
+#m4 _POP()
#include <glib.h>
-
-// Redefine G_DISABLE_DEPRECATED if it was defined before we temporarily undefed it:
-#if defined(GLIBMM_G_DISABLE_DEPRECATED_UNDEFED)
-#define G_DISABLE_DEPRECATED 1
-#undef GLIB_DISABLE_DEPRECATION_WARNINGS
-#undef GLIBMM_G_DISABLE_DEPRECATED_UNDEFED
-#endif
-
-
#include <glibmm/error.h>
#include <sigc++/sigc++.h>
-
+#include <string>
#include <cstddef>
namespace Glib
@@ -62,7 +40,7 @@ namespace Threads
_GMMPROC_EXTRA_NAMESPACE(Threads)
/** @defgroup Threads Threads
- * Thread abstraction; including threads, different mutexes,
+ * %Thread abstraction; including threads, different mutexes,
* conditions and thread private data.
* @{
*/
@@ -74,7 +52,7 @@ class Mutex;
class RecMutex;
class RWLock;
-/** Exception class for thread-related errors.
+/** %Exception class for thread-related errors.
*/
_WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
@@ -90,8 +68,8 @@ _WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
* a Threads::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
+ * @note The thread entry slot doesn't have the void* return value that a
+ * GThreadFunc has. 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
@@ -169,12 +147,10 @@ public:
*/
static void yield();
- GThread* gobj() { return &gobject_; }
- const GThread* gobj() const { return &gobject_; }
+ GThread* gobj();
+ const GThread* gobj() const;
private:
- GThread gobject_;
-
// Glib::Thread can neither be constructed nor deleted.
Thread();
void operator delete(void*, std::size_t);
@@ -195,7 +171,13 @@ private:
class Thread::Exit
{};
-/** @relates Glib::Threads::Thread */
+/** A C++ wrapper for the C object.
+ *
+ * @param gobject The C instance.
+ * @return The C++ wrapper.
+ *
+ * @relates Glib::Threads::Thread
+ */
Thread* wrap(GThread* gobject);
/** Represents a mutex (mutual exclusion).
@@ -203,8 +185,8 @@ Thread* wrap(GThread* gobject);
* 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
+ * @note Glib::Threads::Mutex is not recursive, i.e. a thread will deadlock, if it
+ * already has locked the mutex while calling lock(). Use Glib::Threads::RecMutex
* instead, if you need recursive mutexes.
*/
class Mutex
@@ -251,12 +233,12 @@ private:
* @par Usage example:
* @code
* {
- * Glib::Mutex::Lock lock (mutex); // calls mutex.lock()
+ * Glib::Threads::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
+ * 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.
*/
@@ -319,10 +301,7 @@ private:
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.
@@ -396,10 +375,7 @@ private:
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.
@@ -456,13 +432,13 @@ private:
* 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;
+ * Glib::Threads::Cond data_cond;
+ * Glib::Threads::Mutex data_mutex;
+ * void* current_data = nullptr;
*
* void push_data(void* data)
* {
- * Glib::Mutex::Lock lock (data_mutex);
+ * Glib::Threads::Mutex::Lock lock(data_mutex);
*
* current_data = data;
* data_cond.signal();
@@ -470,18 +446,18 @@ private:
*
* void* pop_data()
* {
- * Glib::Mutex::Lock lock (data_mutex);
+ * Glib::Threads::Mutex::Lock lock(data_mutex);
*
* while (!current_data)
* data_cond.wait(data_mutex);
*
- * void *const data = current_data;
- * current_data = 0;
+ * void* const data = current_data;
+ * current_data = nullptr;
*
* return data;
* }
* @endcode
-*/
+ */
class Cond
{
public:
@@ -491,12 +467,11 @@ public:
/** 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
+ * It is good practice to hold the same lock as the waiting threads, while calling
* this method, though not required.
*/
void broadcast();
@@ -504,7 +479,7 @@ public:
/** 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.
+ * @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
@@ -515,11 +490,40 @@ public:
*/
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 end_time.
+ /** Waits until this thread is woken up on this @a Cond, but not longer
+ * than until the time specified by @a end_time.
* The mutex is unlocked before falling asleep and locked again before resuming.
*
- * @param mutex a @a Mutex that is currently locked.
- * @param end_time a max time to wait.
+ * @par Usage example:
+ * Extending the example presented in the documentation of class Cond.
+ * @code
+ * void* pop_data_timed()
+ * {
+ * Glib::Threads::Mutex::Lock lock(data_mutex);
+ *
+ * // Wait at most 5 seconds.
+ * const gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+ * while (!current_data)
+ * if (!data_cond.wait_until(data_mutex, end_time)
+ * return 0; // timeout
+ *
+ * void* const data = current_data;
+ * current_data = nullptr;
+ *
+ * return data;
+ * }
+ * @endcode
+ * The end time is calculated once, before entering the loop, and reused.
+ * This is the motivation behind the use of absolute time. If a relative time
+ * of 5 seconds were passed directly to the call and a spurious wakeup
+ * occurred, the program would have to start over waiting again, which would
+ * lead to a total wait time of more than 5 seconds.
+ *
+ * @param mutex A @a Mutex that is currently locked.
+ * @param end_time The monotonic time to wait until, in microseconds.
+ * See g_get_monotonic_time().
+ * @return <tt>true</tt> if the condition variable was signalled (or in the case
+ * of a spurious wakeup), <tt>false</tt> if @a end_time has passed.
*
* @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
@@ -544,7 +548,7 @@ private:
*
* It is recommended that all instances of this class are statically allocated.
* The first time an instance is used (get(), set() or replace() is called)
- * gtk+ allocates a scarce OS resource that cannot be deallocated.
+ * glib allocates a scarce OS resource that cannot be deallocated.
*/
template <class T>
class Private
@@ -606,8 +610,7 @@ private:
/* inline implementation */
/***************************************************************************/
-
-/**** Glib::Mutex::Lock ****************************************************/
+/**** Glib::Threads::Mutex::Lock *******************************************/
inline
Mutex::Lock::Lock(Mutex& mutex)
@@ -667,7 +670,7 @@ bool Mutex::Lock::locked() const
}
-/**** Glib::RecMutex::Lock *************************************************/
+/**** Glib::Threads::RecMutex::Lock ****************************************/
inline
RecMutex::Lock::Lock(RecMutex& mutex)
@@ -727,7 +730,7 @@ bool RecMutex::Lock::locked() const
}
-/**** Glib::RWLock::ReaderLock *********************************************/
+/**** Glib::Threads::RWLock::ReaderLock ************************************/
inline
RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
@@ -787,7 +790,7 @@ bool RWLock::ReaderLock::locked() const
}
-/**** Glib::RWLock::WriterLock *********************************************/
+/**** Glib::Threads::RWLock::WriterLock ************************************/
inline
RWLock::WriterLock::WriterLock(RWLock& rwlock)
@@ -846,7 +849,7 @@ bool RWLock::WriterLock::locked() const
return locked_;
}
-/**** Glib::Private ********************************************************/
+/**** Glib::Threads::Private<T> ********************************************/
// static
template <class T>