/* 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) _CONFIGINCLUDE(glibmmconfig.h) _IS_DEPRECATED // This whole file is deprecated. #m4 _PUSH(SECTION_CC_PRE_INCLUDES) //Stop the compiler warnings about using the deprecated API; #define GLIB_DISABLE_DEPRECATION_WARNINGS 1 #m4 _POP() // 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) //Stop the deprecation ifdef guards around the API declarations: #undef G_DISABLE_DEPRECATED #define GLIBMM_G_DISABLE_DEPRECATED_UNDEFED 1 #endif #include // 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 GLIBMM_G_DISABLE_DEPRECATED_UNDEFED #endif #include #include #include #include /* 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::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 { /** @deprecated Thread priorities no longer have any effect. */ _WRAP_ENUM(ThreadPriority, GThreadPriority, NO_GTYPE) /*! @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. */ /** Initializes the GLib thread system. * @deprecated Calling thread_init() is no longer necessary and no longer has any effect. */ void thread_init(GThreadFunctions* vtable = nullptr); /** Returns whether the thread system is initialized. * @return @c true, if the thread system is initialized. * @deprecated This is no longer useful, because the thread system is always initialized. */ bool thread_supported(); /** * @deprecated Use Glib::Threads::NotLock instead. */ enum NotLock { NOT_LOCK }; /** * @deprecated Use Glib::Threads::TryLock instead. */ enum TryLock { TRY_LOCK }; class Mutex; class RecMutex; class RWLock; struct StaticRecMutex; struct StaticRWLock; /** Exception class for thread-related errors. * @deprecated Use Glib::Threads::ThreadError instead. */ _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. * * @deprecated Use Glib::Threads::Thread instead. */ 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 THREAD_PRIORITY_NORMAL. * 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& 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 joinable = true. */ void join(); //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 * @a stack_size is 0. * * 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. * * 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. * * @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 Glib::THREAD_PRIORITY_NORMAL * here as a default. * * @note Only use the extended * create(const sigc::slot&, unsigned long, bool, bool, ThreadPriority) * function, when you really can't use the simple * create(const sigc::slot&, 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 0. * @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 * * @deprecated Use the simpler create() method instead, because all Threads * are now joinable, and bounds and priority parameters now have no effect. */ static Thread* create(const sigc::slot& slot, unsigned long stack_size, bool joinable, bool bound, ThreadPriority priority); /** Returns whether the thread is joinable. * @return Whether the thread is joinable. * * @deprecated All threads are now joinable. */ bool joinable() const; /** 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. * * @deprecated Thread priorities no longer have any effect. */ void set_priority(ThreadPriority priority); /** Returns the priority of the thread. * @return The thread's priority. * * @deprecated Thread priorities no longer have any effect. */ 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*, std::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 catch(...) somewhere in your code. * * @deprecated Use Glib::Threads::Thread::Exit instead. */ class Thread::Exit {}; //TODO: Make sure that Glib::wrap() uses Glib::Threads::wrap() instead. /** @relates Glib::Thread * * @deprecated Use Glib::Threads::wrap(GThread*) instead. */ Thread* wrap(GThread* gobject); struct StaticMutex; /** 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. * * @deprecated Use Glib::Threads::Mutex instead, which can be used statically. */ 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 }; /** 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 } /** 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 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 { 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 * return while still holding the lock and it will be released * properly. * * @deprecated Use Glib::Threads::Mutex::Lock instead. */ 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. * * @deprecated Use Glib::Threads::RecMutex instead, which can be used statically. */ 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 }; /** * * @deprecated Use Glib::Threads::RecMutex instead. */ 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. * * @deprecated Use Glib::Threads::RecMutex instead. */ 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. * * @deprecated Use Glib::Threads::RWLock instead, which can be used statically. */ 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 }; /** * * @deprecated Use Glib::Threads::RWLock instead. */ 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. * * @deprecated Use Glib::Threads::RWLock::ReaderLock instead. */ 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. * * @deprecated Use Glib::Threads::RWLock::WriterLock instead. */ 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 = nullptr; * * 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 = nullptr; * * return data; * } * @endcode * * @deprecated Use Glib::Threads::Cond instead. */ 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 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. * * @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&); }; /** Thread-local data pointer. * * @deprecated Use Glib::Threads::Private instead, which can be used statically. */ template struct StaticPrivate { typedef void (*DestroyNotifyFunc) (void*); static void delete_ptr(void* data); inline T* get(); inline void set(T* data, DestroyNotifyFunc notify_func = &StaticPrivate::delete_ptr); GStaticPrivate* gobj() { return &gobject_; } #ifndef DOXYGEN_SHOULD_SKIP_THIS // Must be public to allow initialization at compile time. GStaticPrivate gobject_; #endif }; /** Thread-local data pointer. * * @deprecated Use Glib::Threads::Private instead. */ template class Private { public: typedef void (*DestructorFunc) (void*); static void delete_ptr(void* data); explicit inline Private(DestructorFunc destructor_func = &Private::delete_ptr); inline T* get(); inline void set(T* data); GPrivate* gobj() { return gobject_; } private: GPrivate* gobject_; // noncopyable Private(const Private&); Private& operator=(const Private&); }; /** @} group Threads */ /*! A glibmm thread example. * @example thread/thread.cc */ #ifndef DOXYGEN_SHOULD_SKIP_THIS /***************************************************************************/ /* inline implementation */ /***************************************************************************/ // internal /** @deprecated This was always for internal glibmm use and is now unecessary even inside glibmm. */ void thread_init_impl(); /**** 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 void StaticPrivate::delete_ptr(void* data) { delete static_cast(data); } /** This is only for use by glibmm itself. */ void* StaticPrivate_get_helper(GStaticPrivate *private_key); template inline T* StaticPrivate::get() { return static_cast(StaticPrivate_get_helper(&gobject_)); } /** This is only for use by glibmm itself. */ void StaticPrivate_set_helper(GStaticPrivate *private_key, gpointer data, GDestroyNotify notify); template inline void StaticPrivate::set(T* data, typename StaticPrivate::DestroyNotifyFunc notify_func) { StaticPrivate_set_helper(&gobject_, data, notify_func); } /**** Glib::Private ********************************************************/ // static template void Private::delete_ptr(void* data) { delete static_cast(data); } /** This is only for use by glibmm itself. */ GPrivate* GPrivate_new_helper(GDestroyNotify notify); template inline Private::Private(typename Private::DestructorFunc destructor_func) : gobject_ (GPrivate_new_helper(destructor_func)) {} template inline T* Private::get() { return static_cast(g_private_get(gobject_)); } template inline void Private::set(T* data) { g_private_set(gobject_, data); } #endif /* DOXYGEN_SHOULD_SKIP_THIS */ } // namespace Glib