diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-11-10 13:26:00 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-11-14 10:43:21 +0100 |
commit | db75f338fb1865fbec12daae64dac4d0a1b9abf8 (patch) | |
tree | e502ea0b726f1dccd35c90660aab43d3b283e045 | |
parent | 53ceee1d8f4967d4fc3a9ece73a8a273583aae5e (diff) | |
download | glibmm-db75f338fb1865fbec12daae64dac4d0a1b9abf8.tar.gz |
Remove deprecated Thread and Threads API.
-rw-r--r-- | examples/Makefile.am | 6 | ||||
-rw-r--r-- | examples/thread/thread.cc | 126 | ||||
-rw-r--r-- | examples/thread/threadpool.cc | 68 | ||||
-rw-r--r-- | glib/glibmm.h | 7 | ||||
-rw-r--r-- | glib/glibmm/dispatcher.cc | 28 | ||||
-rw-r--r-- | glib/glibmm/exceptionhandler.cc | 19 | ||||
-rw-r--r-- | glib/glibmm/filelist.am | 2 | ||||
-rw-r--r-- | glib/glibmm/main.cc | 21 | ||||
-rw-r--r-- | glib/glibmm/main.h | 51 | ||||
-rw-r--r-- | glib/glibmm/threadpool.cc | 255 | ||||
-rw-r--r-- | glib/glibmm/threadpool.h | 200 | ||||
-rw-r--r-- | glib/src/filelist.am | 2 | ||||
-rw-r--r-- | glib/src/thread.ccg | 427 | ||||
-rw-r--r-- | glib/src/thread.hg | 1085 | ||||
-rw-r--r-- | glib/src/threads.ccg | 302 | ||||
-rw-r--r-- | glib/src/threads.hg | 932 |
16 files changed, 1 insertions, 3530 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am index 0de871a7..885552d5 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -32,11 +32,7 @@ check_PROGRAMS = \ options/example \ properties/example \ regex/example \ - settings/settings \ - thread/dispatcher \ - thread/dispatcher2 \ - thread/thread \ - thread/threadpool + settings/settings glibmm_includes = -I$(top_builddir)/glib $(if $(srcdir:.=),-I$(top_srcdir)/glib) giomm_includes = -I$(top_builddir)/gio $(if $(srcdir:.=),-I$(top_srcdir)/gio) diff --git a/examples/thread/thread.cc b/examples/thread/thread.cc deleted file mode 100644 index 7af27350..00000000 --- a/examples/thread/thread.cc +++ /dev/null @@ -1,126 +0,0 @@ - -#include <condition_variable> -#include <iostream> -#include <memory> -#include <mutex> -#include <queue> -#include <thread> -#if defined(_MSC_VER) && (_MSC_VER < 1900) -/* For using noexcept on Visual Studio 2013 */ -#include <glibmmconfig.h> -#endif -#include <glibmm/init.h> -#include <glibmm/random.h> -#include <glibmm/timer.h> - -namespace -{ - -class MessageQueue -{ -public: - MessageQueue(); - ~MessageQueue(); - - void producer(); - void consumer(); - -private: - std::mutex mutex_; - std::condition_variable cond_push_; - std::condition_variable cond_pop_; - std::queue<int> queue_; -}; - -MessageQueue::MessageQueue() -{ -} - -MessageQueue::~MessageQueue() -{ -} - -void -MessageQueue::producer() -{ - Glib::Rand rand(1234); - - for (auto i = 0; i < 200; ++i) - { - { - std::unique_lock<std::mutex> lock(mutex_); - - cond_pop_.wait(lock, [this]() -> bool { return queue_.size() < 64; }); - - queue_.push(i); - std::cout << '*'; - std::cout.flush(); - - // We unlock before notifying, because that is what the documentation suggests: - // http://en.cppreference.com/w/cpp/thread/condition_variable - lock.unlock(); - cond_push_.notify_one(); - } - - if (rand.get_bool()) - continue; - - Glib::usleep(rand.get_int_range(0, 100000)); - } -} - -void -MessageQueue::consumer() -{ - Glib::Rand rand(4567); - - for (;;) - { - { - std::unique_lock<std::mutex> lock(mutex_); - - cond_push_.wait(lock, [this]() -> bool { return !queue_.empty(); }); - - const int i = queue_.front(); - queue_.pop(); - std::cout << "\x08 \x08"; - std::cout.flush(); - - // We unlock before notifying, because that is what the documentation suggests: - // http://en.cppreference.com/w/cpp/thread/condition_variable - lock.unlock(); - cond_pop_.notify_one(); - - if (i >= 199) - break; - } - - if (rand.get_bool()) - continue; - - Glib::usleep(rand.get_int_range(10000, 200000)); - } -} -} - -int -main(int, char**) -{ - Glib::init(); - - MessageQueue queue; - - // TODO: Use std::make_unique() when we use C++14: - const auto producer = - std::unique_ptr<std::thread>(new std::thread(&MessageQueue::producer, &queue)); - - const auto consumer = - std::unique_ptr<std::thread>(new std::thread(&MessageQueue::consumer, &queue)); - - producer->join(); - consumer->join(); - - std::cout << std::endl; - - return 0; -} diff --git a/examples/thread/threadpool.cc b/examples/thread/threadpool.cc deleted file mode 100644 index 885962bc..00000000 --- a/examples/thread/threadpool.cc +++ /dev/null @@ -1,68 +0,0 @@ - -#include <iostream> -#include <mutex> -#include <thread> - -// TODO: Remove this example sometime. Glib::ThreadPool is deprecated. -// TODO: Maybe use std::async() instead? -#undef GLIBMM_DISABLE_DEPRECATED - -#include <glibmmconfig.h> - -#ifdef GLIBMM_DISABLE_DEPRECATED -int -main(int, char**) -{ - // If glibmm is configured with --disable-deprecated-api, - // GLIBMM_DISABLE_DEPRECATED is defined in glibmmconfig.h. - std::cout << "Glib::ThreadPool not available because deprecated API has been disabled." - << std::endl; - return 77; // Tell automake's test harness to skip this test. -} - -#else - -#include <glibmm/random.h> -#include <glibmm/threadpool.h> -#include <glibmm/timer.h> - -namespace -{ - -std::mutex mutex; - -void -print_char(char c) -{ - Glib::Rand rand; - - for (auto i = 0; i < 100; ++i) - { - { - std::lock_guard<std::mutex> lock(mutex); - std::cout << c; - std::cout.flush(); - } - Glib::usleep(rand.get_int_range(10000, 100000)); - } -} - -} // anonymous namespace - -int -main(int, char**) -{ - Glib::ThreadPool pool(10); - - for (auto c = 'a'; c <= 'z'; ++c) - { - pool.push(sigc::bind(sigc::ptr_fun(&print_char), c)); - } - - pool.shutdown(); - - std::cout << std::endl; - - return 0; -} -#endif // GLIBMM_DISABLE_DEPRECATED diff --git a/glib/glibmm.h b/glib/glibmm.h index b82b1430..79d3e1d3 100644 --- a/glib/glibmm.h +++ b/glib/glibmm.h @@ -84,12 +84,6 @@ //#include <glibmm/i18n.h> //This must be included by the application, after system headers such as //<iostream>. -// Include this first because we need it to be the first thing to include <glib.h>, -// 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/base64.h> @@ -140,7 +134,6 @@ #include <glibmm/slisthandle.h> #include <glibmm/spawn.h> #include <glibmm/stringutils.h> -#include <glibmm/threadpool.h> #include <glibmm/timer.h> #include <glibmm/timeval.h> #include <glibmm/timezone.h> diff --git a/glib/glibmm/dispatcher.cc b/glib/glibmm/dispatcher.cc index 83da346d..3c8a65d0 100644 --- a/glib/glibmm/dispatcher.cc +++ b/glib/glibmm/dispatcher.cc @@ -15,10 +15,6 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef GLIBMM_CAN_USE_THREAD_LOCAL -#include <glibmm/threads.h> -#endif - #include <glibmm/dispatcher.h> #include <glibmm/exceptionhandler.h> #include <glibmm/fileutils.h> @@ -147,11 +143,7 @@ protected: explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context); private: -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL static thread_local DispatchNotifier* thread_specific_instance_; -#else - static Glib::Threads::Private<DispatchNotifier> thread_specific_instance_; -#endif std::set<const Dispatcher*> deleted_dispatchers_; @@ -175,11 +167,7 @@ private: // static -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL thread_local DispatchNotifier* DispatchNotifier::thread_specific_instance_ = nullptr; -#else -Glib::Threads::Private<DispatchNotifier> DispatchNotifier::thread_specific_instance_; -#endif DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context) : deleted_dispatchers_(), @@ -282,20 +270,12 @@ DispatchNotifier* DispatchNotifier::reference_instance( const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher) { -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL DispatchNotifier* instance = thread_specific_instance_; -#else - DispatchNotifier* instance = thread_specific_instance_.get(); -#endif if (!instance) { instance = new DispatchNotifier(context); -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL thread_specific_instance_ = instance; -#else - thread_specific_instance_.replace(instance); -#endif } else { @@ -323,11 +303,7 @@ DispatchNotifier::reference_instance( void DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher) { -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL DispatchNotifier* const instance = thread_specific_instance_; -#else - DispatchNotifier* const instance = thread_specific_instance_.get(); -#endif // Yes, the notifier argument is only used to check for sanity. g_return_if_fail(instance == notifier); @@ -344,12 +320,8 @@ DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatc { g_return_if_fail(instance->ref_count_ == 0); // could be < 0 if messed up -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL delete thread_specific_instance_; thread_specific_instance_ = nullptr; -#else - thread_specific_instance_.replace(nullptr); -#endif } } diff --git a/glib/glibmm/exceptionhandler.cc b/glib/glibmm/exceptionhandler.cc index 7a16c789..e80e0093 100644 --- a/glib/glibmm/exceptionhandler.cc +++ b/glib/glibmm/exceptionhandler.cc @@ -19,9 +19,6 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef GLIBMM_CAN_USE_THREAD_LOCAL -#include <glibmm/threads.h> -#endif #include <glibmmconfig.h> #include <glibmm/error.h> #include <glibmm/exceptionhandler.h> @@ -36,11 +33,7 @@ using HandlerList = std::list<sigc::slot<void()>>; // Each thread has its own list of exception handlers // to avoid thread synchronization problems. -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL static thread_local HandlerList* thread_specific_handler_list = nullptr; -#else -static Glib::Threads::Private<HandlerList> thread_specific_handler_list; -#endif static void glibmm_exception_warning(const GError* error) @@ -92,20 +85,12 @@ namespace Glib sigc::connection add_exception_handler(const sigc::slot<void()>& slot) { -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL HandlerList* handler_list = thread_specific_handler_list; -#else - HandlerList* handler_list = thread_specific_handler_list.get(); -#endif if (!handler_list) { handler_list = new HandlerList(); -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL thread_specific_handler_list = handler_list; -#else - thread_specific_handler_list.set(handler_list); -#endif } handler_list->emplace_back(slot); @@ -130,11 +115,7 @@ exception_handlers_invoke() noexcept // handled. If there are no more handlers in the list and the exception // is still unhandled, call glibmm_unexpected_exception(). -#ifdef GLIBMM_CAN_USE_THREAD_LOCAL if (HandlerList* const handler_list = thread_specific_handler_list) -#else - if(HandlerList *const handler_list = thread_specific_handler_list.get()) -#endif { HandlerList::iterator pslot = handler_list->begin(); diff --git a/glib/glibmm/filelist.am b/glib/glibmm/filelist.am index dc6615f5..afeb2b4c 100644 --- a/glib/glibmm/filelist.am +++ b/glib/glibmm/filelist.am @@ -30,7 +30,6 @@ glibmm_files_extra_cc = \ signalproxy_connectionnode.cc \ streamiochannel.cc \ stringutils.cc \ - threadpool.cc \ timer.cc \ timeval.cc \ ustring.cc \ @@ -74,7 +73,6 @@ glibmm_files_extra_h = \ slisthandle.h \ streamiochannel.h \ stringutils.h \ - threadpool.h \ timer.h \ timeval.h \ ustring.h \ diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc index 06521a47..f549e021 100644 --- a/glib/glibmm/main.cc +++ b/glib/glibmm/main.cc @@ -17,13 +17,6 @@ #include <glibmmconfig.h> // May define GLIBMM_DISABLE_DEPRECATED -#ifndef GLIBMM_DISABLE_DEPRECATED -// Include glibmm/thread.h first because we need it to be first to include <glib.h>, -// so we can do an undef trick to still use deprecated API in the header: -#include <glibmm/thread.h> -#include <glibmm/threads.h> -#endif // GLIBMM_DISABLE_DEPRECATED - #include <glibmm/main.h> #include <glibmm/exceptionhandler.h> #include <glibmm/wrap.h> @@ -608,20 +601,6 @@ 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()); -} - -bool -MainContext::wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex) -{ - return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj()); -} -#endif // GLIBMM_DISABLE_DEPRECATED - void MainContext::release() { diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h index 4dbbf150..26718764 100644 --- a/glib/glibmm/main.h +++ b/glib/glibmm/main.h @@ -30,17 +30,6 @@ namespace Glib { -#ifndef GLIBMM_DISABLE_DEPRECATED -class Cond; -class Mutex; - -namespace Threads -{ -class Cond; -class Mutex; -} -#endif // GLIBMM_DISABLE_DEPRECATED - /** @defgroup MainLoop The Main Event Loop * Manages all available sources of events. * @{ @@ -69,16 +58,6 @@ private: GPollFD gobject_; }; -// Concerning SignalTimeout::connect_once(), SignalTimeout::connect_seconds_once() -// and SignalIdle::connect_once(): -// See https://bugzilla.gnome.org/show_bug.cgi?id=396963 and -// http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue. -// It's recommended to replace sigc::slot<void()>& by std::function<void()>& in -// Threads::Thread::create() and ThreadPool::push() at the next ABI break. -// Such a replacement would be a mixed blessing in SignalTimeout and SignalIdle. -// In a single-threaded program auto-disconnection of trackable slots is safe -// and can be useful. - class SignalTimeout { public: @@ -453,36 +432,6 @@ 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); - - // Deprecated mostly because it uses deprecated Glib::Threads:: for parameters. - /** 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 Please use the underlying g_main_context_wait() function if you really need this - * functionality. - */ - bool wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex); -#endif // GLIBMM_DISABLE_DEPRECATED - /** 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 diff --git a/glib/glibmm/threadpool.cc b/glib/glibmm/threadpool.cc deleted file mode 100644 index 7070ccdf..00000000 --- a/glib/glibmm/threadpool.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* 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 <glibmmconfig.h> -#ifndef GLIBMM_DISABLE_DEPRECATED - -#include <glibmm/threadpool.h> -#include <glibmm/exceptionhandler.h> -#include <glibmm/threads.h> -#include <glib.h> -#include <list> - -namespace Glib -{ - -// internal -class ThreadPool::SlotList -{ -public: - SlotList(); - ~SlotList() noexcept; - - // noncopyable - SlotList(const ThreadPool::SlotList&) = delete; - ThreadPool::SlotList& operator=(const ThreadPool::SlotList&) = delete; - - sigc::slot<void()>* push(const sigc::slot<void()>& slot); - sigc::slot<void()> pop(sigc::slot<void()>* slot_ptr); - - void lock_and_unlock(); - -private: - Glib::Threads::Mutex mutex_; - std::list<sigc::slot<void()>> list_; -}; - -ThreadPool::SlotList::SlotList() -{ -} - -ThreadPool::SlotList::~SlotList() noexcept -{ -} - -sigc::slot<void()>* -ThreadPool::SlotList::push(const sigc::slot<void()>& slot) -{ - Threads::Mutex::Lock lock(mutex_); - - list_.emplace_back(slot); - return &list_.back(); -} - -sigc::slot<void()> -ThreadPool::SlotList::pop(sigc::slot<void()>* slot_ptr) -{ - sigc::slot<void()> slot; - - { - Threads::Mutex::Lock lock(mutex_); - - std::list<sigc::slot<void()>>::iterator pslot = list_.begin(); - while (pslot != list_.end() && slot_ptr != &*pslot) - ++pslot; - - if (pslot != list_.end()) - { - slot = *pslot; - list_.erase(pslot); - } - } - - return slot; -} - -void -ThreadPool::SlotList::lock_and_unlock() -{ - mutex_.lock(); - mutex_.unlock(); -} - -} // namespace Glib - -namespace -{ - -static void -call_thread_entry_slot(void* data, void* user_data) -{ - try - { - Glib::ThreadPool::SlotList* const slot_list = - static_cast<Glib::ThreadPool::SlotList*>(user_data); - - sigc::slot<void()> slot(slot_list->pop(static_cast<sigc::slot<void()>*>(data))); - - slot(); - } - catch (Glib::Threads::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(); - } -} - -} // anonymous namespace - -namespace Glib -{ - -ThreadPool::ThreadPool(int max_threads, bool exclusive) -: gobject_(nullptr), slot_list_(new SlotList()) -{ - GError* error = nullptr; - - gobject_ = g_thread_pool_new(&call_thread_entry_slot, slot_list_, max_threads, exclusive, &error); - - if (error) - { - delete slot_list_; - slot_list_ = nullptr; - Glib::Error::throw_exception(error); - } -} - -ThreadPool::~ThreadPool() noexcept -{ - if (gobject_) - g_thread_pool_free(gobject_, 1, 1); - - if (slot_list_) - { - slot_list_->lock_and_unlock(); - delete slot_list_; - } -} - -void -ThreadPool::push(const sigc::slot<void()>& slot) -{ - sigc::slot<void()>* const slot_ptr = slot_list_->push(slot); - - GError* error = nullptr; - g_thread_pool_push(gobject_, slot_ptr, &error); - - if (error) - { - slot_list_->pop(slot_ptr); - Glib::Error::throw_exception(error); - } -} - -void -ThreadPool::set_max_threads(int max_threads) -{ - GError* error = nullptr; - g_thread_pool_set_max_threads(gobject_, max_threads, &error); - - if (error) - Glib::Error::throw_exception(error); -} - -int -ThreadPool::get_max_threads() const -{ - return g_thread_pool_get_max_threads(gobject_); -} - -unsigned int -ThreadPool::get_num_threads() const -{ - return g_thread_pool_get_num_threads(gobject_); -} - -unsigned int -ThreadPool::unprocessed() const -{ - return g_thread_pool_unprocessed(gobject_); -} - -bool -ThreadPool::get_exclusive() const -{ - g_return_val_if_fail(gobject_ != nullptr, false); - - return gobject_->exclusive; -} - -void -ThreadPool::shutdown(bool immediately) -{ - if (gobject_) - { - g_thread_pool_free(gobject_, immediately, 1); - gobject_ = nullptr; - } - - if (slot_list_) - { - slot_list_->lock_and_unlock(); - delete slot_list_; - slot_list_ = nullptr; - } -} - -// static -void -ThreadPool::set_max_unused_threads(int max_threads) -{ - g_thread_pool_set_max_unused_threads(max_threads); -} - -// static -int -ThreadPool::get_max_unused_threads() -{ - return g_thread_pool_get_max_unused_threads(); -} - -// static -unsigned int -ThreadPool::get_num_unused_threads() -{ - return g_thread_pool_get_num_unused_threads(); -} - -// static -void -ThreadPool::stop_unused_threads() -{ - g_thread_pool_stop_unused_threads(); -} - -} // namespace Glib - -#endif // GLIBMM_DISABLE_DEPRECATED diff --git a/glib/glibmm/threadpool.h b/glib/glibmm/threadpool.h deleted file mode 100644 index 06285f0d..00000000 --- a/glib/glibmm/threadpool.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef _GLIBMM_THREADPOOL_H -#define _GLIBMM_THREADPOOL_H - -/* 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 <glibmmconfig.h> - -#ifndef GLIBMM_DISABLE_DEPRECATED - -#include <sigc++/sigc++.h> - -extern "C" { -using GThreadPool = struct _GThreadPool; -} - -namespace Glib -{ - -/** @defgroup ThreadPools Thread Pools - * Pools of threads to execute work concurrently. - * - * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14. - * - * @{ - */ - -// TODO: Is std::async() an appropriate replacement to mention for this deprecated API? - -/** A pool of threads to execute work concurrently. - * - * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14. - */ -class ThreadPool -{ -public: - /** Constructs a new thread pool. - * Whenever you call ThreadPool::push(), either a new thread is created or an - * unused one is reused. At most @a max_threads threads are running - * concurrently for this thread pool. @a max_threads = -1 allows - * unlimited threads to be created for this thread pool. - * - * The parameter @a exclusive determines, whether the thread pool owns all - * threads exclusive or whether the threads are shared globally. If @a - * exclusive is <tt>true</tt>, @a max_threads threads are started immediately - * and they will run exclusively for this thread pool until it is destroyed - * by ~ThreadPool(). If @a exclusive is <tt>false</tt>, threads are created - * when needed and shared between all non-exclusive thread pools. This - * implies that @a max_threads may not be -1 for exclusive thread pools. - * - * @param max_threads The maximal number of threads to execute concurrently - * in the new thread pool, -1 means no limit. - * @param exclusive Should this thread pool be exclusive? - * @throw Glib::ThreadError An error can only occur when @a exclusive is - * set to <tt>true</tt> and not all @a max_threads threads could be created. - */ - explicit ThreadPool(int max_threads = -1, bool exclusive = false); - virtual ~ThreadPool() noexcept; - - // See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue. - // TODO: At the next ABI break, consider changing const sigc::slot<void()>& slot - // to const std::function<void()>& func, if it can be assumed that all supported - // compilers understand the C++11 template class std::function<>. - /** Inserts @a slot into the list of tasks to be executed by the pool. - * When the number of currently running threads is lower than the maximal - * allowed number of threads, a new thread is started (or reused). Otherwise - * @a slot stays in the queue until a thread in this pool finishes its - * previous task and processes @a slot. - * - * Because sigc::trackable is not thread-safe, if the slot represents a - * non-static class method and is created by sigc::mem_fun(), the class concerned - * should not derive from sigc::trackable. You can use, say, boost::bind() or, - * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun(). - * - * @param slot A new task for the thread pool. - * @throw Glib::ThreadError An error can only occur when a new thread - * couldn't be created. In that case @a slot is simply appended to the - * queue of work to do. - */ - void push(const sigc::slot<void()>& slot); - - /** Sets the maximal allowed number of threads for the pool. - * A value of -1 means that the maximal number of threads is unlimited. - * Setting @a max_threads to 0 means stopping all work for pool. It is - * effectively frozen until @a max_threads is set to a non-zero value again. - * - * A thread is never terminated while it is still running. Instead the - * maximal number of threads only has effect for the allocation of new - * threads in ThreadPool::push(). A new thread is allocated whenever the - * number of currently running threads in the pool is smaller than the - * maximal number. - * - * @param max_threads A new maximal number of threads for the pool. - * @throw Glib::ThreadError An error can only occur when a new thread - * couldn't be created. - */ - void set_max_threads(int max_threads); - - /** Returns the maximal number of threads for the pool. - * @return The maximal number of threads. - */ - int get_max_threads() const; - - /** Returns the number of threads currently running in the pool. - * @return The number of threads currently running. - */ - unsigned int get_num_threads() const; - - /** Returns the number of tasks still unprocessed in the pool. - * @return The number of unprocessed tasks. - */ - unsigned int unprocessed() const; - - /** Returns whether all threads are exclusive to this pool. - * @return Whether all threads are exclusive to this pool. - */ - bool get_exclusive() const; - - /** Frees all resources allocated for the pool. - * If @a immediately is <tt>true</tt>, no new task is processed. Otherwise the - * pool is not freed before the last task is processed. Note however, that no - * thread of this pool is interrupted while processing a task. Instead at least - * all still running threads can finish their tasks before the pool is freed. - * - * This method does not return before all tasks to be processed (dependent on - * @a immediately, whether all or only the currently running) are ready. - * After calling shutdown() the pool must not be used anymore. - * - * @param immediately Should the pool shut down immediately? - */ - void shutdown(bool immediately = false); - - /** Sets the maximal number of unused threads to @a max_threads. - * If @a max_threads is -1, no limit is imposed on the number of unused threads. - * @param max_threads Maximal number of unused threads. - */ - static void set_max_unused_threads(int max_threads); - - /** Returns the maximal allowed number of unused threads. - * @return The maximal number of unused threads. - */ - static int get_max_unused_threads(); - - /** Returns the number of currently unused threads. - * @return The number of currently unused threads. - */ - static unsigned int get_num_unused_threads(); - - /** Stops all currently unused threads. - * This does not change the maximal number of unused threads. This function can - * be used to regularly stop all unused threads e.g. from Glib::signal_timeout(). - */ - static void stop_unused_threads(); - - GThreadPool* gobj() { return gobject_; } - const GThreadPool* gobj() const { return gobject_; } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - class SlotList; -#endif - -private: - GThreadPool* gobject_; - SlotList* slot_list_; - - ThreadPool(const ThreadPool&); - ThreadPool& operator=(const ThreadPool&); -}; - -/** @} group ThreadPools */ - -/***************************************************************************/ -/* inline implementation */ -/***************************************************************************/ - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -/**** Glib::Private ********************************************************/ - -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -} // namespace Glib - -#endif // GLIBMM_DISABLE_DEPRECATED - -#endif /* _GLIBMM_THREADPOOL_H */ diff --git a/glib/src/filelist.am b/glib/src/filelist.am index 6b52c61a..a8c2c406 100644 --- a/glib/src/filelist.am +++ b/glib/src/filelist.am @@ -36,8 +36,6 @@ glibmm_files_any_hg = \ regex.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 deleted file mode 100644 index 7965ab99..00000000 --- a/glib/src/thread.ccg +++ /dev/null @@ -1,427 +0,0 @@ -/* 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) -{ - const auto 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 nullptr; -} - -} // extern "C" - -} // anonymous namespace - -namespace Glib -{ - -// 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. -// TODO: Remove this when we can break ABI. -void -thread_init_impl() -{ - // Make sure the exception map is initialized before creating any thread. - Glib::Error::register_init(); -} - -/**** Glib::Thread *********************************************************/ - -// static -Thread* -Thread::create(const sigc::slot<void()>& slot, bool /* joinable */) -{ - // Make a copy of slot on the heap - const auto slot_copy = new sigc::slot<void()>(slot); - - GError* error = nullptr; - - const auto thread = g_thread_try_new(nullptr, &call_thread_entry_slot, slot_copy, &error); - - if (error) - { - delete slot_copy; - // Glib::Error::throw_exception() will probably wrap G_THREAD_ERROR in a - // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError. - if (error->domain == G_THREAD_ERROR) - throw Glib::ThreadError(error); - else - Glib::Error::throw_exception(error); - } - - return reinterpret_cast<Thread*>(thread); -} - -// static -Thread* -Thread::create(const sigc::slot<void()>& slot, unsigned long stack_size, bool joinable, bool bound, - ThreadPriority priority) -{ - // Make a copy of slot on the heap - const auto slot_copy = new sigc::slot<void()>(slot); - - GError* error = nullptr; - - const auto thread = g_thread_create_full(&call_thread_entry_slot, slot_copy, stack_size, joinable, - bound, (GThreadPriority)priority, &error); - - if (error) - { - delete slot_copy; - // Glib::Error::throw_exception() will probably wrap G_THREAD_ERROR in a - // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError. - if (error->domain == G_THREAD_ERROR) - throw Glib::ThreadError(error); - else - Glib::Error::throw_exception(error); - } - - return reinterpret_cast<Thread*>(thread); -} - -// static -Thread* -Thread::self() -{ - return reinterpret_cast<Thread*>(g_thread_self()); -} - -void -Thread::join() -{ - g_thread_join(&gobject_); -} - -bool -Thread::joinable() const -{ - return true; // An appropriate result now that this is deprecated because all threads are now - // joinable. -} - -void -Thread::set_priority(ThreadPriority priority) -{ - g_thread_set_priority(&gobject_, (GThreadPriority)priority); -} - -ThreadPriority -Thread::get_priority() const -{ - return THREAD_PRIORITY_NORMAL; // An appropriate result now that this is deprecated because the - // priority concept has been removed. -} - -void -thread_init(GThreadFunctions* /* vtable */) -{ - // g_thread_init() is deprecated and now does nothing, - // so we do not even call it. That avoids a need to link to gthread-2.0, - // which contains the empty g_thread_init() implementation. - // g_thread_init(vtable); - - Glib::thread_init_impl(); -} - -bool -thread_supported() -{ - // MSVC++ needs the != 0 to avoid an int -> bool cast warning. - return (g_thread_supported() != 0); -} - -// static -void -Thread::yield() -{ - g_thread_yield(); -} - -Thread* -wrap(GThread* gobject) -{ - return reinterpret_cast<Thread*>(gobject); -} - -/**** Glib::StaticMutex ****************************************************/ - -void -StaticMutex::lock() -{ - g_static_mutex_lock(&gobject_); -} - -bool -StaticMutex::trylock() -{ - return g_static_mutex_trylock(&gobject_); -} - -void -StaticMutex::unlock() -{ - g_static_mutex_unlock(&gobject_); -} - -StaticMutex::operator Mutex&() -{ - // If GStaticMutex is implemented as struct (e.g. on Linux), its first struct - // member (runtime_mutex) is a GMutex pointer. If the gthread implementation - // is native (i.e. the vtable pointer passed to g_thread_init() was 0), then - // the runtime_mutex pointer is unused, and the rest of the GStaticMutex - // struct resembles the mutex data. - // - // On Win32, GStaticMutex is just a typedef to struct _GMutex*. Either way, - // the first sizeof(GMutex*) bytes of GStaticMutex always resemble a GMutex - // pointer. The gthread implementation relies on that, and we'll also do so. - - GMutex*& runtime_mutex = reinterpret_cast<GMutex*&>(gobject_); - - // Fortunately, it cannot hurt if we set this to the GMutex pointer returned - // by g_static_mutex_get_mutex(). Either we just overwrite it with the same - // value, or it was unused anyway. Doing that allows casting the pointer - // location to a Glib::Mutex reference (its only data member is a GMutex*). - - runtime_mutex = g_static_mutex_get_mutex(&gobject_); - - return reinterpret_cast<Mutex&>(runtime_mutex); -} - -/**** Glib::Mutex **********************************************************/ - -Mutex::Mutex() -: gobject_(g_mutex_new()) // TODO: Use a statically-allocated GMutext instead, with g_mutex_init(). -{ -} - -Mutex::~Mutex() -{ - g_mutex_free(gobject_); -} - -void -Mutex::lock() -{ - g_mutex_lock(gobject_); -} - -bool -Mutex::trylock() -{ - return g_mutex_trylock(gobject_); -} - -void -Mutex::unlock() -{ - g_mutex_unlock(gobject_); -} - -/**** Glib::StaticRecMutex *************************************************/ - -void -StaticRecMutex::lock() -{ - g_static_rec_mutex_lock(&gobject_); -} - -bool -StaticRecMutex::trylock() -{ - return g_static_rec_mutex_trylock(&gobject_); -} - -void -StaticRecMutex::unlock() -{ - g_static_rec_mutex_unlock(&gobject_); -} - -void -StaticRecMutex::lock_full(unsigned int depth) -{ - g_static_rec_mutex_lock_full(&gobject_, depth); -} - -unsigned int -StaticRecMutex::unlock_full() -{ - return g_static_rec_mutex_unlock_full(&gobject_); -} - -StaticRecMutex::operator RecMutex&() -{ - return static_cast<RecMutex&>(*this); -} - -/**** Glib::RecMutex *******************************************************/ - -RecMutex::RecMutex() -{ - g_static_rec_mutex_init(&gobject_); -} - -RecMutex::~RecMutex() -{ - g_static_rec_mutex_free(&gobject_); -} - -/**** Glib::StaticRWLock ***************************************************/ - -void -StaticRWLock::reader_lock() -{ - g_static_rw_lock_reader_lock(&gobject_); -} - -bool -StaticRWLock::reader_trylock() -{ - return g_static_rw_lock_reader_trylock(&gobject_); -} - -void -StaticRWLock::reader_unlock() -{ - g_static_rw_lock_reader_unlock(&gobject_); -} - -void -StaticRWLock::writer_lock() -{ - g_static_rw_lock_writer_lock(&gobject_); -} - -bool -StaticRWLock::writer_trylock() -{ - return g_static_rw_lock_writer_trylock(&gobject_); -} - -void -StaticRWLock::writer_unlock() -{ - g_static_rw_lock_writer_unlock(&gobject_); -} - -StaticRWLock::operator RWLock&() -{ - return static_cast<RWLock&>(*this); -} - -/**** Glib::RWLock *********************************************************/ - -RWLock::RWLock() -{ - g_static_rw_lock_init(&gobject_); - - // GLib doesn't have GRWLock, only GStaticRWLock. Force initialization - // of the mutex and the condition variables now, to mimic the behaviour - // of a (hypothetical) GRWLock. - - if (g_static_mutex_get_mutex(&gobject_.mutex)) - { - gobject_.read_cond = g_cond_new(); - gobject_.write_cond = g_cond_new(); - } -} - -RWLock::~RWLock() -{ - g_static_rw_lock_free(&gobject_); -} - -/**** Glib::Cond ***********************************************************/ - -Cond::Cond() : gobject_(g_cond_new()) -{ -} - -Cond::~Cond() -{ - g_cond_free(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::timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time) -{ - return g_cond_timed_wait(gobject_, mutex.gobj(), const_cast<Glib::TimeVal*>(&abs_time)); -} - -void* -StaticPrivate_get_helper(GStaticPrivate* private_key) -{ - return g_static_private_get(private_key); -} - -void -StaticPrivate_set_helper(GStaticPrivate* private_key, gpointer data, GDestroyNotify notify) -{ - return g_static_private_set(private_key, data, notify); -} - -GPrivate* -GPrivate_new_helper(GDestroyNotify notify) -{ - return g_private_new(notify); -} - -} // namespace Glib diff --git a/glib/src/thread.hg b/glib/src/thread.hg deleted file mode 100644 index 045ce2b6..00000000 --- a/glib/src/thread.hg +++ /dev/null @@ -1,1085 +0,0 @@ -/* 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 <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 GLIBMM_G_DISABLE_DEPRECATED_UNDEFED -#endif - - -#include <glibmm/error.h> -#include <glibmm/timeval.h> -#include <sigc++/sigc++.h> - -#include <cstddef> - -/* 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: - - Thread(const Thread&) = delete; - Thread& operator=(const Thread&) = delete; - - 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 = true</tt>. - */ - 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 <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. - * - * 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 <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 - * - * @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<void()>& 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); -}; - -/** %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. - * - * @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(const Mutex&) = delete; - Mutex& operator=(const Mutex&) = delete; - - ~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_; -}; - -/** 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. - * - * @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_; - - -}; - - -/** 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); - - Lock(const RecMutex::Lock&) = delete; - RecMutex::Lock& operator=(const RecMutex::Lock&) = delete; - - inline ~Lock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RecMutex& mutex_; - bool locked_; -}; - - -/** 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(const RWLock&) = delete; - RWLock& operator=(const RWLock&) = delete; - - ~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); - - ReaderLock(const RWLock::ReaderLock&) = delete; - RWLock::ReaderLock& operator=(const RWLock::ReaderLock&) = delete; - - inline ~ReaderLock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RWLock& rwlock_; - bool locked_; -}; - -/** 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); - - WriterLock(const RWLock::WriterLock&) = delete; - RWLock::WriterLock& operator=(const RWLock::WriterLock&) = delete; - - inline ~WriterLock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RWLock& rwlock_; - bool locked_; -}; - -/** 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(const Cond&) = delete; - Cond& operator=(const Cond&) = delete; - - ~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_; -}; - - -/** Thread-local data pointer. - * - * @deprecated Use Glib::Threads::Private instead, which can be used statically. - */ -template <class T> -struct StaticPrivate -{ - using DestroyNotifyFunc = void (*) (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 -}; - -/** Thread-local data pointer. - * - * @deprecated Use Glib::Threads::Private instead. - */ -template <class T> -class Private -{ -public: - - Private(const Private<T>&) = delete; - Private<T>& operator=(const Private<T>&) = delete; - - using DestructorFunc = void (*) (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_; -}; - -/** @} 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 <class T> -void StaticPrivate<T>::delete_ptr(void* data) -{ - delete static_cast<T*>(data); -} - -/** This is only for use by glibmm itself. - */ -void* StaticPrivate_get_helper(GStaticPrivate *private_key); - -template <class T> inline -T* StaticPrivate<T>::get() -{ - return static_cast<T*>(StaticPrivate_get_helper(&gobject_)); -} - -/** This is only for use by glibmm itself. - */ -void StaticPrivate_set_helper(GStaticPrivate *private_key, gpointer data, GDestroyNotify notify); - -template <class T> inline -void StaticPrivate<T>::set(T* data, typename StaticPrivate<T>::DestroyNotifyFunc notify_func) -{ - StaticPrivate_set_helper(&gobject_, data, notify_func); -} - - -/**** Glib::Private ********************************************************/ - -// static -template <class T> -void Private<T>::delete_ptr(void* data) -{ - delete static_cast<T*>(data); -} - -/** This is only for use by glibmm itself. - */ -GPrivate* GPrivate_new_helper(GDestroyNotify notify); - -template <class T> inline -Private<T>::Private(typename Private<T>::DestructorFunc destructor_func) -: - gobject_ (GPrivate_new_helper(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 - diff --git a/glib/src/threads.ccg b/glib/src/threads.ccg deleted file mode 100644 index 8b66493c..00000000 --- a/glib/src/threads.ccg +++ /dev/null @@ -1,302 +0,0 @@ -/* 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> - -/* Why reinterpret_cast<Thread*>(gobject) is needed: - * - * A Thread instance is in fact always a GThread instance. - * Unfortunately, GThread cannot be a member of Thread, - * because it is an opaque struct. Also, the C interface does not provide - * any hooks to install a destroy notification handler, thus we cannot - * wrap it dynamically either. - * - * The cast works because Thread does not have any member data, and - * it is impossible to derive from it. This is ensured by not implementing - * the (private) default constructor. - * This trick is used also in classes declared as _CLASS_OPAQUE_REFCOUNTED. - */ - -namespace -{ - -extern "C" { - -static void* -call_thread_entry_slot(void* data) -{ - const auto slot = reinterpret_cast<sigc::slot_base*>(data); - - try - { - // Recreate the specific slot. - (*static_cast<sigc::slot<void()>*>(slot))(); - } - catch (Glib::Threads::Thread::Exit&) - { - // Just exit from the thread. The Threads::Thread::Exit exception - // is our sane C++ replacement of g_thread_exit(). - } - catch (...) - { - Glib::exception_handlers_invoke(); - } - - delete slot; - return nullptr; -} - -} // extern "C" - -} // anonymous namespace - -namespace Glib -{ - -namespace Threads -{ - -/**** Glib::Threads::Thread ************************************************/ - -// static -Thread* -Thread::create(const sigc::slot<void()>& slot, const std::string& name) -{ - // Make a copy of slot on the heap. - const auto slot_copy = new sigc::slot<void()>(slot); - - GError* error = nullptr; - auto thread = g_thread_try_new( - name.empty() ? nullptr : name.c_str(), &call_thread_entry_slot, slot_copy, &error); - - if (error) - { - delete slot_copy; - Glib::Error::throw_exception(error); - } - if (!thread) - { - delete slot_copy; - } - return reinterpret_cast<Thread*>(thread); -} - -// static -Thread* -Thread::create(const sigc::slot<void()>& slot) -{ - return create(slot, std::string()); -} - -// static -Thread* -Thread::self() -{ - return reinterpret_cast<Thread*>(g_thread_self()); -} - -void -Thread::join() -{ - g_thread_join(reinterpret_cast<GThread*>(this)); -} - -// static -void -Thread::yield() -{ - g_thread_yield(); -} - -GThread* -Thread::gobj() -{ - return reinterpret_cast<GThread*>(this); -} - -const GThread* -Thread::gobj() const -{ - return reinterpret_cast<const GThread*>(this); -} - -Thread* -wrap(GThread* gobject) -{ - return reinterpret_cast<Thread*>(gobject); -} - -/**** Glib::Threads::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_); -} - -Mutex* -wrap(GMutex* gobject) -{ - return reinterpret_cast<Mutex*>(gobject); -} - -/**** Glib::Threads::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_); -} - -RecMutex* -wrap(GRecMutex* gobject) -{ - return reinterpret_cast<RecMutex*>(gobject); -} - -/**** Glib::Threads::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_); -} - -RWLock::RWLock() -{ - g_rw_lock_init(&gobject_); -} - -RWLock::~RWLock() -{ - g_rw_lock_clear(&gobject_); -} - -/**** Glib::Threads::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 deleted file mode 100644 index afd8877f..00000000 --- a/glib/src/threads.hg +++ /dev/null @@ -1,932 +0,0 @@ -/* 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) -// 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> -#include <glibmm/error.h> -#include <sigc++/sigc++.h> -#include <string> -#include <cstddef> - -namespace Glib -{ - -/** - * @deprecated The entire Glib::Threads API is deprecated in favor of the - * standard C++ concurrency API in C++11 and C++14. - */ -namespace Threads -{ -//The GMMPROC_EXTRA_NAMESPACE() macro is a hint to generate_wrap_init.pl to put it in the Threads sub-namespace -_GMMPROC_EXTRA_NAMESPACE(Threads) - -/** @defgroup Threads Threads - * %Thread abstraction; including threads, different mutexes, - * conditions and thread private data. - * - * @deprecated The entire Glib::Threads API is deprecated in favor of the - * standard C++ concurrency API in C++11 and C++14. - * @{ - */ - -/// @deprecated Please use std::lock_guard or std::unique_lock instead. -enum NotLock { NOT_LOCK }; - -/// @deprecated Please use std::lock_guard or std::unique_lock instead. -enum TryLock { TRY_LOCK }; - -class Mutex; -class RecMutex; -class RWLock; - -/** %Exception class for thread-related errors. - * - * @deprecated Please use std::lock_guard or std::unique_lock 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. - * 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 Threads::Thread::Exit exception, which will be caught by the internal thread - * entry function. - * - * @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. - * - * @deprecated Please use std::thread instead. - */ -class Thread -{ -public: - - Thread(const Thread&) = delete; - Thread& operator=(const Thread&) = delete; - - class Exit; - - //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue. - // TODO: At the next ABI break, consider changing const sigc::slot<void()>& slot - // to const std::function<void()>& func, if it can be assumed that all supported - // compilers understand the C++11 template class std::function<>. - /** Creates a new thread. - * You can wait for this thread's termination by calling join(). - * - * 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 Threads::ThreadError exception is thrown. - * - * Because sigc::trackable is not thread-safe, if the slot represents a - * non-static class method and is created by sigc::mem_fun(), the class concerned - * should not derive from sigc::trackable. You can use, say, boost::bind() or, - * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun(). - * - * @param slot A slot to execute in the new thread. - * @return The new Thread* on success. - * @throw Glib::Threads::ThreadError - */ - static Thread* create(const sigc::slot<void()>& slot); - - // TODO: At next ABI break, remove the single parameter create - // method and default name to std::string() - - /** Creates a new named thread. - * You can wait for this thread's termination by calling join(). - * - * 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 Threads::ThreadError exception is thrown. - * - * Because sigc::trackable is not thread-safe, if the slot represents a - * non-static class method and is created by sigc::mem_fun(), the class concerned - * should not derive from sigc::trackable. You can use, say, boost::bind() or, - * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun(). - * - * The @a name can be useful for discriminating threads in a debugger. - * It is not used for other purposes and does not have to be unique. - * Some systems restrict the length of @a name to 16 bytes. - * - * @param slot A slot to execute in the new thread. - * @param name A name for the new thread. - * @return The new Thread* on success. - * @throw Glib::Threads::ThreadError - * - * @newin{2,36} - */ - static Thread* create(const sigc::slot<void()>& slot, const std::string& name); - - /** 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::Threads::Thread object are released. - */ - 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(); - const GThread* gobj() const; - -private: - // Glib::Thread can neither be constructed nor deleted. - Thread(); - void operator delete(void*, std::size_t); -}; - -/** %Exception class used to exit from a thread. - * @code - * throw Glib::Threads::Thread::Exit(); - * @endcode - * Write this if you want to exit from a thread created by Threads::Thread::create(). - * Of course you must make sure not to catch Threads::Thread::Exit by accident, i.e. - * when using <tt>catch(...)</tt> somewhere in your code. - * - * @deprecated Please use std::thread instead. - */ -class Thread::Exit -{}; - -/** A C++ wrapper for the C object. - * - * @param gobject The C instance. - * @return The C++ wrapper. - * - * @relates Glib::Threads::Thread - * - * @deprecated Please use std::thread instead. - */ -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 -- - * it will make your life much easier. - * - * @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. - * - * @deprecated Please use std::mutex instead. - */ -class Mutex -{ -public: - class Lock; - - Mutex(); - - Mutex(const Mutex&) = delete; - Mutex& operator=(const Mutex&) = delete; - - ~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_; -}; - -/** Utility class for exception-safe mutex locking. - * @par Usage example: - * @code - * { - * 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 - * <tt>return</tt> while still holding the lock and it will be released - * properly. - * - * @deprecated Please use std::lock_guard or std::unique_lock instead. - */ -class Mutex::Lock -{ -public: - explicit inline Lock(Mutex& mutex); - inline Lock(Mutex& mutex, NotLock); - inline Lock(Mutex& mutex, TryLock); - - Lock(const Mutex::Lock&) = delete; - Mutex::Lock& operator=(const Mutex::Lock&) = delete; - - inline ~Lock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - Mutex& mutex_; - bool locked_; -}; - -/** A C++ wrapper for the C object. - * Do not use operator delete on the returned pointer. If the caller owns the - * GMutex object, the caller must destroy it in the same way as if this function - * had not been called. - * - * @param gobject The C instance. - * @result The GMutex* cast to a Glib::Threads::Mutex*. - * - * @relates Glib::Threads::Mutex - */ -Mutex* wrap(GMutex* gobject); - -/** This represents a recursive mutex. - * It is similar to a Mutex with the difference - * that it is possible to lock a RecMutex multiple times in the same - * thread without deadlock. When doing so, care has to be taken to - * unlock the recursive mutex as often as it has been locked. - * - * @deprecated Please use std::recursive_mutex instead. - */ -class RecMutex -{ -public: - class Lock; - - RecMutex(); - - RecMutex(const RecMutex&) = delete; - RecMutex& operator=(const RecMutex&) = delete; - - ~RecMutex(); - - void lock(); - bool trylock(); - void unlock(); - - GRecMutex* gobj() { return &gobject_; } - -private: - GRecMutex gobject_; -}; - -/** Utility class for exception-safe locking of recursive mutexes. - * - * @deprecated Please use std::lock_guard or std::unique_lock instead. - */ -class RecMutex::Lock -{ -public: - explicit inline Lock(RecMutex& mutex); - inline Lock(RecMutex& mutex, NotLock); - inline Lock(RecMutex& mutex, TryLock); - - Lock(const RecMutex::Lock&) = delete; - RecMutex::Lock& operator=(const RecMutex::Lock&) = delete; - - inline ~Lock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RecMutex& mutex_; - bool locked_; -}; - -/** A C++ wrapper for the C object. - * Do not use operator delete on the returned pointer. If the caller owns the - * GRecMutex object, the caller must destroy it in the same way as if this function - * had not been called. - * - * @param gobject The C instance. - * @result The GRecMutex* cast to a Glib::Threads::RecMutex*. - * - * @relates Glib::Threads::RecMutex - */ -RecMutex* wrap(GRecMutex* gobject); - -/** This represents a reader-writer lock. - * It is similar to a Mutex in that it allows - * multiple threads to coordinate access to a shared resource. - * - * The difference to a mutex is that a reader-writer lock discriminates - * between read-only ('reader') and full ('writer') access. While only - * one thread at a time is allowed write access (by holding the 'writer' - * lock via writer_lock()), multiple threads can gain - * simultaneous read-only access (by holding the 'reader' lock via - * reader_lock()). - * - * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex. - */ -class RWLock -{ -public: - class ReaderLock; - class WriterLock; - - RWLock(); - - RWLock(const RWLock&) = delete; - RWLock& operator=(const RWLock&) = delete; - - ~RWLock(); - - void reader_lock(); - bool reader_trylock(); - void reader_unlock(); - - void writer_lock(); - bool writer_trylock(); - void writer_unlock(); - - GRWLock* gobj() { return &gobject_; } - -private: - GRWLock gobject_; -}; - -/** Utility class for exception-safe locking of read/write locks. - * - * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex. - */ -class RWLock::ReaderLock -{ -public: - explicit inline ReaderLock(RWLock& rwlock); - inline ReaderLock(RWLock& rwlock, NotLock); - inline ReaderLock(RWLock& rwlock, TryLock); - - ReaderLock(const RWLock::ReaderLock&) = delete; - RWLock::ReaderLock& operator=(const RWLock::ReaderLock&) = delete; - - inline ~ReaderLock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RWLock& rwlock_; - bool locked_; -}; - -/** Utility class for exception-safe locking of read/write locks. - * - * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex. - */ -class RWLock::WriterLock -{ -public: - explicit inline WriterLock(RWLock& rwlock); - inline WriterLock(RWLock& rwlock, NotLock); - inline WriterLock(RWLock& rwlock, TryLock); - - WriterLock(const RWLock::WriterLock&) = delete; - RWLock::WriterLock& operator=(const RWLock::WriterLock&) = delete; - - inline ~WriterLock(); - - inline void acquire(); - inline bool try_acquire(); - inline void release(); - inline bool locked() const; - -private: - RWLock& rwlock_; - bool locked_; -}; - -/** 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. - * - * @deprecated Please use std::condition_variable instead. - * - * @par Usage example: - * @code - * Glib::Threads::Cond data_cond; - * Glib::Threads::Mutex data_mutex; - * void* current_data = nullptr; - * - * void push_data(void* data) - * { - * Glib::Threads::Mutex::Lock lock(data_mutex); - * - * current_data = data; - * data_cond.signal(); - * } - * - * void* pop_data() - * { - * Glib::Threads::Mutex::Lock lock(data_mutex); - * - * while (!current_data) - * data_cond.wait(data_mutex); - * - * void* const data = current_data; - * current_data = nullptr; - * - * return data; - * } - * @endcode - */ -class Cond -{ -public: - Cond(); - - Cond(const Cond&) = delete; - Cond& operator=(const Cond&) = delete; - - ~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 threads, 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 specified by @a end_time. - * The mutex is unlocked before falling asleep and locked again before resuming. - * - * @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 nullptr; // 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 - * 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_; -}; - -/** Thread-local data pointer. - * - * 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) - * glib allocates a scarce OS resource that cannot be deallocated. - * - * @deprecated Please use the thread_local keyword instead. - */ -template <class T> -class Private -{ -public: - Private(const Private<T>&) = delete; - Private<T>& operator=(const Private<T>&) = delete; - - using DestructorFunc = void (*) (void*); - - /** Deletes static_cast<T*>(data) - */ - static void delete_ptr(void* data); - - /** Constructor. - * - * @param destructor_func Function pointer, or <tt>nullptr</tt>. If @a destructor_func is not <tt>nullptr</tt> - * and the stored data pointer is not <tt>nullptr</tt>, this function is called when replace() - * is called and when the thread exits. - */ - explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr); - - /** Gets the pointer stored in the calling thread. - * - * @return If no value has yet been set in this thread, <tt>nullptr</tt> is returned. - */ - inline T* get(); - - /** Sets the pointer in the calling thread without calling <tt>destructor_func()</tt>. - */ - inline void set(T* data); - - /** Sets the pointer in the calling thread and calls <tt>destructor_func()</tt>. - * If a function pointer (and not <tt>nullptr</tt>) was specified in the constructor, and - * the stored data pointer before the call to replace() is not <tt>nullptr</tt>, then - * <tt>destructor_func()</tt> is called with this old pointer value. - * - * @newin{2,32} - */ - inline void replace(T* data); - - GPrivate* gobj() { return gobject_; } - -private: - GPrivate gobject_; -}; - -/** @} group Threads */ - -/*! A glibmm thread example. - * @example thread/thread.cc - */ - - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -/***************************************************************************/ -/* inline implementation */ -/***************************************************************************/ - -/**** Glib::Threads::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::Threads::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::Threads::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::Threads::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::Threads::Private<T> ********************************************/ - -// 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_INIT(destructor_func); - // does not compile with --enable-warnings=fatal. - // GPrivate is a struct, and G_PRIVATE_INIT is an initializer of type { ... }. - // G_PRIVATE_INIT can be used only in initializations. - const GPrivate temp = G_PRIVATE_INIT(destructor_func); - gobject_ = temp; -} - -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); -} - -template <class T> inline -void Private<T>::replace(T* data) -{ - g_private_replace(&gobject_, data); -} - -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -} //namespace Threads - -} // namespace Glib |