aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-30 13:57:11 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-30 13:57:11 +0000
commitdc35f2a0535e9b5a67cfd908d87d91713447ec4e (patch)
tree44c2ac5d857dd651358de3ccd6f939855f484167
parent4082c5da864b30104810c7dd3104a31b914b7cf7 (diff)
downloadpaludis-dc35f2a0535e9b5a67cfd908d87d91713447ec4e.tar.gz
paludis-dc35f2a0535e9b5a67cfd908d87d91713447ec4e.tar.xz
r3674@snowflake: ciaranm | 2007-06-30 14:56:49 +0100
Basic idle actions support
-rw-r--r--paludis/util/action_queue.cc18
-rw-r--r--paludis/util/action_queue.hh2
-rw-r--r--paludis/util/files.m42
-rw-r--r--paludis/util/idle_action_pool.cc78
-rw-r--r--paludis/util/idle_action_pool.hh46
-rw-r--r--paludis/util/idle_action_pool_TEST.cc61
-rw-r--r--paludis/util/thread_pool.cc52
-rw-r--r--paludis/util/thread_pool.hh40
-rw-r--r--paludis/util/thread_pool_TEST.cc56
9 files changed, 347 insertions, 8 deletions
diff --git a/paludis/util/action_queue.cc b/paludis/util/action_queue.cc
index 2421ef9..3e994a9 100644
--- a/paludis/util/action_queue.cc
+++ b/paludis/util/action_queue.cc
@@ -23,7 +23,7 @@
#ifdef PALUDIS_ENABLE_THREADS
# include <paludis/util/mutex.hh>
# include <paludis/util/condition_variable.hh>
-# include <paludis/util/thread.hh>
+# include <paludis/util/thread_pool.hh>
# include <list>
#endif
@@ -39,12 +39,13 @@ namespace paludis
ConditionVariable condition;
bool should_finish;
std::list<tr1::function<void () throw ()> > queue;
- Thread thread;
+ ThreadPool threads;
void finish()
{
Lock l(mutex);
should_finish = true;
+ condition.broadcast();
}
void thread_func()
@@ -73,23 +74,26 @@ namespace paludis
}
}
- Implementation() :
- should_finish(false),
- thread(tr1::bind(tr1::mem_fn(&Implementation::thread_func), this))
+ Implementation(const unsigned n_threads) :
+ should_finish(false)
{
+ for (unsigned x(0) ; x < n_threads ; ++x)
+ threads.create_thread(tr1::bind(tr1::mem_fn(&Implementation::thread_func), this));
}
#endif
};
}
-ActionQueue::ActionQueue() :
- PrivateImplementationPattern<ActionQueue>(new Implementation<ActionQueue>)
+ActionQueue::ActionQueue(const unsigned n_threads) :
+ PrivateImplementationPattern<ActionQueue>(new Implementation<ActionQueue>(n_threads))
{
}
ActionQueue::~ActionQueue()
{
+#ifdef PALUDIS_ENABLE_THREADS
enqueue(tr1::bind(tr1::mem_fn(&Implementation<ActionQueue>::finish), _imp.get()));
+#endif
}
void
diff --git a/paludis/util/action_queue.hh b/paludis/util/action_queue.hh
index 46c8d2a..5cdceb2 100644
--- a/paludis/util/action_queue.hh
+++ b/paludis/util/action_queue.hh
@@ -29,7 +29,7 @@ namespace paludis
private PrivateImplementationPattern<ActionQueue>
{
public:
- ActionQueue();
+ ActionQueue(const unsigned n_threads = 1);
~ActionQueue();
void enqueue(const tr1::function<void () throw ()> &);
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index debd87c..7c4e724 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -22,6 +22,7 @@ add(`fd_output_stream', `hh')
add(`fs_entry', `hh', `cc', `fwd', `test', `testscript')
add(`fd_holder', `hh')
add(`graph', `hh', `cc', `impl', `test')
+add(`idle_action_pool', `hh', `cc', `test')
add(`iterator', `hh', `test')
add(`instantiation_policy', `hh', `impl', `test')
add(`is_file_with_extension', `hh', `cc', `se', `test', `testscript')
@@ -42,6 +43,7 @@ add(`stringify', `hh', `test')
add(`strip', `hh', `cc', `test')
add(`system', `hh', `cc', `test', `testscript')
add(`thread', `hh', `cc', `test')
+add(`thread_pool', `hh', `cc', `test')
add(`tokeniser', `hh', `cc', `test')
add(`tr1_memory', `hh')
add(`tr1_type_traits', `hh')
diff --git a/paludis/util/idle_action_pool.cc b/paludis/util/idle_action_pool.cc
new file mode 100644
index 0000000..d745964
--- /dev/null
+++ b/paludis/util/idle_action_pool.cc
@@ -0,0 +1,78 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/idle_action_pool.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+#include <paludis/util/action_queue.hh>
+
+using namespace paludis;
+
+template class InstantiationPolicy<IdleActionPool, instantiation_method::SingletonTag>;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<IdleActionPool>
+ {
+#ifdef PALUDIS_ENABLE_THREADS
+ ActionQueue pool;
+
+ Implementation() :
+ pool(5)
+ {
+ }
+#endif
+ };
+}
+
+
+IdleActionPool::IdleActionPool() :
+ PrivateImplementationPattern<IdleActionPool>(new Implementation<IdleActionPool>)
+{
+}
+
+IdleActionPool::~IdleActionPool()
+{
+}
+
+void
+IdleActionPool::required_idle_action(const tr1::function<void () throw ()> & f)
+{
+#ifdef PALUDIS_ENABLE_THREADS
+ _imp->pool.enqueue(f);
+#else
+ f();
+#endif
+}
+
+void
+IdleActionPool::optional_idle_action(
+#ifdef PALUDIS_ENABLE_THREADS
+ const tr1::function<void () throw ()> & f
+#else
+ const tr1::function<void () throw ()> &
+#endif
+ )
+{
+#ifdef PALUDIS_ENABLE_THREADS
+ _imp->pool.enqueue(f);
+#endif
+}
+
diff --git a/paludis/util/idle_action_pool.hh b/paludis/util/idle_action_pool.hh
new file mode 100644
index 0000000..c94d92d
--- /dev/null
+++ b/paludis/util/idle_action_pool.hh
@@ -0,0 +1,46 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_IDLE_ACTION_POOL_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_IDLE_ACTION_POOL_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/tr1_functional.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE IdleActionPool :
+ public InstantiationPolicy<IdleActionPool, instantiation_method::SingletonTag>,
+ private PrivateImplementationPattern<IdleActionPool>
+ {
+ friend class InstantiationPolicy<IdleActionPool, instantiation_method::SingletonTag>;
+
+ private:
+ IdleActionPool();
+ ~IdleActionPool();
+
+ public:
+ void required_idle_action(const tr1::function<void () throw ()> &);
+ void optional_idle_action(const tr1::function<void () throw ()> &);
+ };
+}
+
+#endif
diff --git a/paludis/util/idle_action_pool_TEST.cc b/paludis/util/idle_action_pool_TEST.cc
new file mode 100644
index 0000000..eefdf13
--- /dev/null
+++ b/paludis/util/idle_action_pool_TEST.cc
@@ -0,0 +1,61 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/idle_action_pool.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+#include <sys/time.h>
+
+using namespace test;
+using namespace paludis;
+
+namespace
+{
+ void make_true(bool & b) throw ()
+ {
+ b = true;
+ }
+}
+
+namespace test_cases
+{
+ struct IdleActionPoolTest : TestCase
+ {
+ IdleActionPoolTest() : TestCase("idle action pool") { }
+
+ void run()
+ {
+ bool x(false);
+ IdleActionPool::get_instance()->required_idle_action(tr1::bind(&make_true, tr1::ref(x)));
+ while (true)
+ {
+ TEST_CHECK(true);
+ if (x)
+ break;
+
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 1000;
+ nanosleep(&t, 0);
+ }
+ }
+ } test_action_queue;
+}
+
+
diff --git a/paludis/util/thread_pool.cc b/paludis/util/thread_pool.cc
new file mode 100644
index 0000000..e009a9f
--- /dev/null
+++ b/paludis/util/thread_pool.cc
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/thread_pool.hh>
+#include <paludis/util/thread.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <list>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ThreadPool>
+ {
+ std::list<tr1::shared_ptr<Thread> > threads;
+ };
+}
+
+ThreadPool::ThreadPool() :
+ PrivateImplementationPattern<ThreadPool>(new Implementation<ThreadPool>)
+{
+}
+
+ThreadPool::~ThreadPool()
+{
+}
+
+void
+ThreadPool::create_thread(const tr1::function<void () throw ()> & f)
+{
+ _imp->threads.push_back(make_shared_ptr(new Thread(f)));
+}
+
diff --git a/paludis/util/thread_pool.hh b/paludis/util/thread_pool.hh
new file mode 100644
index 0000000..644c11f
--- /dev/null
+++ b/paludis/util/thread_pool.hh
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_THREAD_POOL_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_THREAD_POOL_HH 1
+
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE ThreadPool :
+ private PrivateImplementationPattern<ThreadPool>
+ {
+ public:
+ ThreadPool();
+ ~ThreadPool();
+
+ void create_thread(const tr1::function<void () throw ()> &);
+ };
+}
+
+#endif
diff --git a/paludis/util/thread_pool_TEST.cc b/paludis/util/thread_pool_TEST.cc
new file mode 100644
index 0000000..cc12dea
--- /dev/null
+++ b/paludis/util/thread_pool_TEST.cc
@@ -0,0 +1,56 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/thread_pool.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+#include <vector>
+#include <algorithm>
+
+using namespace test;
+using namespace paludis;
+
+namespace
+{
+ void make_one(int & b) throw ()
+ {
+ b = 1;
+ }
+}
+
+namespace test_cases
+{
+ struct ThreadPoolTest : TestCase
+ {
+ ThreadPoolTest() : TestCase("thread pool") { }
+
+ void run()
+ {
+ const int n_threads = 10;
+ std::vector<int> t(n_threads, 0);
+ {
+ ThreadPool p;
+ for (int x(0) ; x < n_threads ; ++x)
+ p.create_thread(tr1::bind(&make_one, tr1::ref(t[x])));
+ }
+ TEST_CHECK(n_threads == std::count(t.begin(), t.end(), 1));
+ }
+ } test_thread_pool;
+}
+