diff options
Diffstat (limited to 'libs/glibmm2/glibmm/threadpool.cc')
-rw-r--r-- | libs/glibmm2/glibmm/threadpool.cc | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/libs/glibmm2/glibmm/threadpool.cc b/libs/glibmm2/glibmm/threadpool.cc new file mode 100644 index 0000000000..db9b089c9a --- /dev/null +++ b/libs/glibmm2/glibmm/threadpool.cc @@ -0,0 +1,245 @@ +// -*- c++ -*- +/* $Id$ */ + +/* Copyright (C) 2002 The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glibmm/threadpool.h> +#include <glibmm/exceptionhandler.h> +#include <glib.h> +#include <list> +#include <glibmmconfig.h> + +GLIBMM_USING_STD(list) + + +namespace Glib +{ + +// internal +class ThreadPool::SlotList +{ +public: + SlotList(); + ~SlotList(); + + sigc::slot<void>* push(const sigc::slot<void>& slot); + sigc::slot<void> pop(sigc::slot<void>* slot_ptr); + + void lock_and_unlock(); + +private: + Glib::Mutex mutex_; + std::list< sigc::slot<void> > list_; + + // noncopyable + SlotList(const ThreadPool::SlotList&); + ThreadPool::SlotList& operator=(const ThreadPool::SlotList&); +}; + +ThreadPool::SlotList::SlotList() +{} + +ThreadPool::SlotList::~SlotList() +{} + +sigc::slot<void>* ThreadPool::SlotList::push(const sigc::slot<void>& slot) +{ + Mutex::Lock lock (mutex_); + + list_.push_back(slot); + return &list_.back(); +} + +sigc::slot<void> ThreadPool::SlotList::pop(sigc::slot<void>* slot_ptr) +{ + sigc::slot<void> slot; + + { + 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::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_ (0), + slot_list_ (new SlotList()) +{ + GError* error = 0; + + gobject_ = g_thread_pool_new( + &call_thread_entry_slot, slot_list_, max_threads, exclusive, &error); + + if(error) + { + delete slot_list_; + slot_list_ = 0; + Glib::Error::throw_exception(error); + } +} + +ThreadPool::~ThreadPool() +{ + 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 = 0; + 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 = 0; + 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_ != 0, false); + + return gobject_->exclusive; +} + +void ThreadPool::shutdown(bool immediately) +{ + if(gobject_) + { + g_thread_pool_free(gobject_, immediately, 1); + gobject_ = 0; + } + + if(slot_list_) + { + slot_list_->lock_and_unlock(); + delete slot_list_; + slot_list_ = 0; + } +} + +// 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 + |