diff options
Diffstat (limited to 'libs/glibmm2/glibmm/thread.h')
-rw-r--r-- | libs/glibmm2/glibmm/thread.h | 1082 |
1 files changed, 1082 insertions, 0 deletions
diff --git a/libs/glibmm2/glibmm/thread.h b/libs/glibmm2/glibmm/thread.h new file mode 100644 index 0000000000..a4fa61da0b --- /dev/null +++ b/libs/glibmm2/glibmm/thread.h @@ -0,0 +1,1082 @@ +// -*- c++ -*- +// Generated by gtkmmproc -- DO NOT MODIFY! +#ifndef _GLIBMM_THREAD_H +#define _GLIBMM_THREAD_H + + +/* $Id$ */ + +/* 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 Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <glib/gthread.h> +#include <cstddef> + +#include <sigc++/sigc++.h> +#include <glibmm/error.h> +#include <glibmm/timeval.h> + +/* Shadow THREAD_PRIORITY_NORMAL macro (from winbase.h). + */ +#if defined(THREAD_PRIORITY_NORMAL) && !defined(GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL) +enum { GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL = THREAD_PRIORITY_NORMAL }; +#undef THREAD_PRIORITY_NORMAL +enum { THREAD_PRIORITY_NORMAL = GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL }; +#define THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL +#define GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL 1 +#endif + + +/** Initializer macro for Glib::StaticMutex. + * @relates Glib::StaticMutex + * @hideinitializer + */ +#define GLIBMM_STATIC_MUTEX_INIT { G_STATIC_MUTEX_INIT } + +/** Initializer macro for Glib::StaticRecMutex. + * @relates Glib::StaticRecMutex + * @hideinitializer + */ +#define GLIBMM_STATIC_REC_MUTEX_INIT { G_STATIC_REC_MUTEX_INIT } + +/** Initializer macro for Glib::StaticRWLock. + * @relates Glib::StaticRWLock + * @hideinitializer + */ +#define GLIBMM_STATIC_RW_LOCK_INIT { G_STATIC_RW_LOCK_INIT } + +/** Initializer macro for Glib::StaticPrivate. + * @relates Glib::StaticPrivate + * @hideinitializer + */ +#define GLIBMM_STATIC_PRIVATE_INIT { G_STATIC_PRIVATE_INIT } + + +namespace Glib +{ + +/** @addtogroup glibmmEnums Enums and Flags */ + +/** Specifies the priority of a thread. + * @note It is not guaranteed, that threads with different priorities really + * behave accordingly. On some systems (e.g. Linux) only <tt>root</tt> can + * increase priorities. On other systems (e.g. Solaris) there doesn't seem to + * be different scheduling for different priorities. All in all try to avoid + * being dependent on priorities. + * @ingroup glibmmEnums + */ +enum ThreadPriority +{ + THREAD_PRIORITY_LOW, + THREAD_PRIORITY_NORMAL, + THREAD_PRIORITY_HIGH, + THREAD_PRIORITY_URGENT +}; + + +/*! @var ThreadPriority THREAD_PRIORITY_LOW + * A priority lower than normal. + */ +/*! @var ThreadPriority THREAD_PRIORITY_NORMAL + * The default priority. + */ +/*! @var ThreadPriority THREAD_PRIORITY_HIGH + * A priority higher than normal. + */ +/*! @var ThreadPriority THREAD_PRIORITY_URGENT + * The highest priority. + */ + + +/** @defgroup Threads Threads + * Thread abstraction; including threads, different mutexes, + * conditions and thread private data. + * @{ + */ + +enum NotLock { NOT_LOCK }; +enum TryLock { TRY_LOCK }; + +/** Initializes the GLib thread system. + * Before you use a thread related function in glibmm, you should initialize + * the thread system. This is done by calling Glib::thread_init(). + * + * @note You should only call thread_init() with a non-<tt>0</tt> parameter + * if you really know what you are doing. + * + * @note thread_init() must not be called directly or indirectly as + * a callback from glibmm. Also no mutexes may be currently locked while + * calling thread_init(). + * + * thread_init() might only be called once. On the second call it will + * abort with an error. If you want to make sure that the thread system + * is initialized, you can do that too: + * @code + * if(!Glib::thread_supported()) Glib::thread_init(); + * @endcode + * After that line either the thread system is initialized, or the program + * will abort if no thread system is available in GLib, i.e. either + * @c G_THREADS_ENABLED is not defined or @c G_THREADS_IMPL_NONE is defined. + * + * If no thread system is available and @a vtable is <tt>0</tt> or if not all + * elements of @a vtable are non-<tt>0</tt>, then thread_init() will abort. + * + * @note To use thread_init() in your program, you have to link with the + * libraries that the command <tt>pkg-config --libs gthread-2.0</tt> + * outputs. This is not the case for all the other thread related functions + * of glibmm. Those can be used without having to link with the thread + * libraries. (You @em have to link with <tt>gthread-2.0</tt> if you actually + * want to use threads in your application, though.) + * + * @param vtable A function table of type @c GThreadFunctions, that provides + * the entry points to the thread system to be used. + */ +inline void thread_init(GThreadFunctions* vtable = 0); + +/** Returns whether the thread system is initialized. + * @return @c true, if the thread system is initialized. + */ +inline bool thread_supported(); + + +class Mutex; +class RecMutex; +class RWLock; +struct StaticMutex; +struct StaticRecMutex; +struct StaticRWLock; + + +/** Exception class for thread-related errors. + */ +class ThreadError : public Glib::Error +{ +public: + enum Code + { + AGAIN + }; + + ThreadError(Code error_code, const Glib::ustring& error_message); + explicit ThreadError(GError* gobject); + Code code() const; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +private: + static void throw_func(GError* gobject); + friend void wrap_init(); // uses throw_func() +#endif +}; + + +/** 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; + + /** 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. + * + * @param slot A slot to execute in the new thread. + * @param joinable Should this thread be joinable? + * @return The new Thread* on success. + * @throw Glib::ThreadError + */ + static Thread* create(const sigc::slot<void>& slot, bool joinable); + + /** 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 + * @a stack_size is <tt>0</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. + * If @a bound is @c true, this thread will be scheduled in the system scope, + * otherwise the implementation is free to do scheduling in the process + * scope. The first variant is more expensive resource-wise, but generally + * faster. On some systems (e.g. Linux) all threads are bound. + * + * 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. + * + * @note It is not guaranteed, that threads with different priorities really + * behave accordingly. On some systems (e.g. Linux) only root can increase + * priorities. On other systems (e.g. Solaris) there doesn't seem to be + * different scheduling for different priorities. All in all try to avoid + * being dependent on priorities. Use <tt>Glib::THREAD_PRIORITY_NORMAL</tt> + * here as a default. + * + * @note Only use the extended + * create(const sigc::slot<void>&, unsigned long, bool, bool, ThreadPriority) + * function, when you really can't use the simple + * create(const sigc::slot<void>&, bool) + * instead. The latter overload does not take @a stack_size, @a bound and + * @a priority as arguments, as they should only be used for cases, where + * it is inevitable. + * + * @param slot A slot to execute in the new thread. + * @param stack_size A stack size for the new thread, or <tt>0</tt>. + * @param joinable Should this thread be joinable? + * @param bound Should this thread be bound to a system thread? + * @param priority A priority for the thread. + * @return The new Thread* on success. + * @throw Glib::ThreadError + */ + static Thread* create(const sigc::slot<void>& slot, unsigned long stack_size, + bool joinable, bool bound, ThreadPriority priority); + + /** Returns the Thread* corresponding to the calling thread. + * @return The current thread. + */ + static Thread* self(); + + /** Returns whether the thread is joinable. + * @return Whether the thread is joinable. + */ + bool joinable() const; + + /** 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 = true</tt>. + */ + void join(); + + /** Changes the priority of the thread to @a priority. + * @note It is not guaranteed, that threads with different priorities really + * behave accordingly. On some systems (e.g. Linux) only @c root can + * increase priorities. On other systems (e.g. Solaris) there doesn't seem + * to be different scheduling for different priorities. All in all try to + * avoid being dependent on priorities. + * @param priority A new priority for the thread. + */ + void set_priority(ThreadPriority priority); + + /** Returns the priority of the thread. + * @return The thread's priority. + */ + ThreadPriority get_priority() const; + + /** 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); + + +/** Like Glib::Mutex, but can be defined at compile time. + * Use @c GLIBMM_STATIC_MUTEX_INIT to initialize a StaticMutex: + * @code + * Glib::StaticMutex mutex = GLIBMM_STATIC_MUTEX_INIT; + * @endcode + * A StaticMutex can be used without calling Glib::thread_init(), it will + * 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. + */ +struct StaticMutex +{ + void lock(); + bool trylock(); + void unlock(); + + operator Mutex&(); + + GStaticMutex* gobj() { return &gobject_; } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // Must be public to allow initialization at compile time. + GStaticMutex gobject_; +#endif +}; + +/** 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 -- + * it will make your life much easier. + * + * @note Before creating a Glib::Mutex, Glib::thread_init() has to be called. + * + * @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&); +}; + + +/** Like Glib::RecMutex, but can be defined at compile time. + * Use @c GLIBMM_STATIC_REC_MUTEX_INIT to initialize a StaticRecMutex: + * @code + * Glib::StaticRecMutex mutex = GLIBMM_STATIC_REC_MUTEX_INIT; + * @endcode + * A StaticRecMutex can be used without calling Glib::thread_init(), it will + * 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. + */ +struct StaticRecMutex +{ + void lock(); + bool trylock(); + void unlock(); + + void lock_full(unsigned int depth); + unsigned int unlock_full(); + + operator RecMutex&(); + + GStaticRecMutex* gobj() { return &gobject_; } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // Must be public to allow initialization at compile time. + GStaticRecMutex gobject_; +#endif +}; + +class RecMutex : public StaticRecMutex +{ +public: + class Lock; + + RecMutex(); + ~RecMutex(); + +private: + // noncopyable + RecMutex(const RecMutex&); + RecMutex& operator=(const RecMutex&); +}; + +/** 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&); +}; + + +/** Like Glib::RWLock, but can be defined at compile time. + * Use @c GLIBMM_STATIC_RW_LOCK_INIT to initialize a StaticRWLock: + * @code + * Glib::StaticRWLock rw_lock = GLIBMM_STATIC_RW_LOCK_INIT; + * @endcode + * A StaticRWLock can be used without calling Glib::thread_init(), it will + * 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. + */ +struct StaticRWLock +{ + void reader_lock(); + bool reader_trylock(); + void reader_unlock(); + + void writer_lock(); + bool writer_trylock(); + void writer_unlock(); + + operator RWLock&(); + + GStaticRWLock* gobj() { return &gobject_; } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // Must be public to allow initialization at compile time. + GStaticRWLock gobject_; +#endif +}; + +class RWLock : public StaticRWLock +{ +public: + class ReaderLock; + class WriterLock; + + RWLock(); + ~RWLock(); + +private: + // noncopyable + RWLock(const RWLock&); + RWLock& operator=(const RWLock&); +}; + +/** 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 = NULL; + * + * void push_data (void* data) + * { + * data_mutex.lock(); + * current_data = data; + * data_cond.signal(); + * data_mutex.unlock(); + * } + * + * void* pop_data () + * { + * void* data; + * + * data_mutex.lock(); + * while (!current_data) + * data_cond.wait(data_mutex); + * data = current_data; + * current_data = NULL; + * data_mutex.unlock(); + * 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. + * + * @note This method can also be used if @a Glib::thread_init() has not yet been + * called and will do nothing then. + */ + 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. + * + * @note This method can also be used if @a Glib::thread_init() has not yet been + * called and will do nothing then. + */ + 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. + * + * This method can also be used if @a Glib::thread_init() has not yet been + * called and will immediately return then. + * + * @param mutex a @a Mutex that is currently locked. + * + * @note It is important to use the @a wait() and @a timed_wait() 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. + * + * This function can also be used, if @a Glib::thread_init() has not yet been + * called and will immediately return @c true then. + * + * @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 timed_wait() 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 timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time); + + GCond* gobj() { return gobject_; } + +private: + GCond* gobject_; + + // noncopyable + Cond(const Cond&); + Cond& operator=(const Cond&); +}; + + +template <class T> +struct StaticPrivate +{ + typedef void (*DestroyNotifyFunc) (void*); + + static void delete_ptr(void* data); + + inline T* get(); + inline void set(T* data, DestroyNotifyFunc notify_func = &StaticPrivate<T>::delete_ptr); + + GStaticPrivate* gobj() { return &gobject_; } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // Must be public to allow initialization at compile time. + GStaticPrivate gobject_; +#endif +}; + +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 */ +/***************************************************************************/ + +// internal +void thread_init_impl(); + +/* This function must be inline, to avoid an unnecessary dependency on + * libgthread even if the thread system is not used. libgthread might + * not even be available if GLib was compiled without thread support. + */ +inline +void thread_init(GThreadFunctions* vtable) +{ + g_thread_init(vtable); + Glib::thread_init_impl(); +} + +inline +bool thread_supported() +{ + //MSVC++ needs the != 0 to avoid an int -> bool cast warning. + return (g_thread_supported() != 0); +} + + +/**** 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::StaticPrivate **************************************************/ + +// static +template <class T> +void StaticPrivate<T>::delete_ptr(void* data) +{ + delete static_cast<T*>(data); +} + +template <class T> inline +T* StaticPrivate<T>::get() +{ + return static_cast<T*>(g_static_private_get(&gobject_)); +} + +template <class T> inline +void StaticPrivate<T>::set(T* data, typename StaticPrivate<T>::DestroyNotifyFunc notify_func) +{ + g_static_private_set(&gobject_, data, notify_func); +} + + +/**** 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) +: + gobject_ (g_private_new(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 */ + +} // namespace Glib + + +#endif /* _GLIBMM_THREAD_H */ + |