summaryrefslogtreecommitdiff
path: root/libs/glibmm2/glibmm/threadpool.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/glibmm2/glibmm/threadpool.cc')
-rw-r--r--libs/glibmm2/glibmm/threadpool.cc245
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
+