aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-28 15:24:05 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-28 15:24:05 +0000
commitcc8e0f1a8e2396df9402897bb358ae1544d96467 (patch)
treeea094e7fc6ee00092f6116658442c7c922d0dfe2
parented20e3bc7a0fcef8cfd75f07508318f99cb0d7d5 (diff)
downloadpaludis-cc8e0f1a8e2396df9402897bb358ae1544d96467.tar.gz
paludis-cc8e0f1a8e2396df9402897bb358ae1544d96467.tar.xz
Move executors into util
-rw-r--r--paludis/util/executor-fwd.hh29
-rw-r--r--paludis/util/executor.cc153
-rw-r--r--paludis/util/executor.hh68
-rw-r--r--paludis/util/files.m41
-rw-r--r--src/clients/cave/cmd_sync.cc121
5 files changed, 252 insertions, 120 deletions
diff --git a/paludis/util/executor-fwd.hh b/paludis/util/executor-fwd.hh
new file mode 100644
index 0000000..b507976
--- /dev/null
+++ b/paludis/util/executor-fwd.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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_EXECUTOR_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_EXECUTOR_FWD_HH 1
+
+namespace paludis
+{
+ struct Executor;
+ struct Executive;
+}
+
+#endif
diff --git a/paludis/util/executor.cc b/paludis/util/executor.cc
new file mode 100644
index 0000000..90fec4e
--- /dev/null
+++ b/paludis/util/executor.cc
@@ -0,0 +1,153 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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/executor.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/condition_variable.hh>
+#include <paludis/util/thread.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <map>
+#include <list>
+
+using namespace paludis;
+
+typedef std::multimap<std::string, std::tr1::shared_ptr<Executive> > Queues;
+typedef std::list<std::tr1::shared_ptr<Executive> > ReadyForPost;
+
+Executive::~Executive()
+{
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Executor>
+ {
+ int pending;
+ int active;
+ int done;
+
+ Queues queues;
+ ReadyForPost ready_for_post;
+ Mutex mutex;
+ ConditionVariable condition;
+
+ Implementation() :
+ pending(0),
+ active(0),
+ done(0)
+ {
+ }
+ };
+}
+
+Executor::Executor() :
+ PrivateImplementationPattern<Executor>(new Implementation<Executor>)
+{
+}
+
+Executor::~Executor()
+{
+}
+
+void
+Executor::_one(const std::tr1::shared_ptr<Executive> executive)
+{
+ executive->execute_threaded();
+
+ Lock lock(_imp->mutex);
+ _imp->ready_for_post.push_back(executive);
+ _imp->condition.signal();
+}
+
+
+int
+Executor::pending() const
+{
+ return _imp->pending;
+}
+
+int
+Executor::active() const
+{
+ return _imp->active;
+}
+
+int
+Executor::done() const
+{
+ return _imp->done;
+}
+
+void
+Executor::add(const std::tr1::shared_ptr<Executive> & x)
+{
+ ++_imp->pending;
+ _imp->queues.insert(std::make_pair(x->queue_name(), x));
+}
+
+void
+Executor::execute()
+{
+ typedef std::map<std::string, std::tr1::shared_ptr<Thread> > Running;
+ Running running;
+
+ Lock lock(_imp->mutex);
+ while (true)
+ {
+ bool any(false);
+ for (Queues::iterator q(_imp->queues.begin()), q_end(_imp->queues.end()) ;
+ q != q_end ; )
+ {
+ if ((running.end() != running.find(q->first)) || ! q->second->can_run())
+ {
+ ++q;
+ continue;
+ }
+
+ ++_imp->active;
+ --_imp->pending;
+ q->second->pre_execute_exclusive();
+ running.insert(std::make_pair(q->first, make_shared_ptr(new Thread(
+ std::tr1::bind(&Executor::_one, this, q->second)))));
+ _imp->queues.erase(q++);
+ any = true;
+ }
+
+ if ((! any) && running.empty())
+ break;
+
+ _imp->condition.wait(_imp->mutex);
+
+ for (ReadyForPost::iterator p(_imp->ready_for_post.begin()), p_end(_imp->ready_for_post.end()) ;
+ p != p_end ; ++p)
+ {
+ --_imp->active;
+ ++_imp->done;
+ running.erase((*p)->queue_name());
+ (*p)->post_execute_exclusive();
+ }
+
+ _imp->ready_for_post.clear();
+ }
+}
+
+template class PrivateImplementationPattern<Executor>;
+
diff --git a/paludis/util/executor.hh b/paludis/util/executor.hh
new file mode 100644
index 0000000..e468de2
--- /dev/null
+++ b/paludis/util/executor.hh
@@ -0,0 +1,68 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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_EXECUTOR_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_EXECUTOR_HH 1
+
+#include <paludis/util/executor-fwd.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <string>
+#include <tr1/memory>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE Executive
+ {
+ public:
+ virtual ~Executive() = 0;
+
+ virtual std::string queue_name() const = 0;
+ virtual std::string unique_id() const = 0;
+ virtual bool can_run() const = 0;
+
+ virtual void pre_execute_exclusive() = 0;
+ virtual void execute_threaded() = 0;
+ virtual void post_execute_exclusive() = 0;
+ };
+
+ class PALUDIS_VISIBLE Executor :
+ private PrivateImplementationPattern<Executor>
+ {
+ private:
+ void _one(const std::tr1::shared_ptr<Executive>);
+
+ public:
+ Executor();
+ ~Executor();
+
+ int pending() const;
+ int active() const;
+ int done() const;
+
+ void add(const std::tr1::shared_ptr<Executive> & x);
+
+ void execute();
+ };
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<Executor>;
+#endif
+}
+
+#endif
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index 4809415..387a68b 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -27,6 +27,7 @@ add(`dir_iterator', `hh', `cc', `fwd', `se', `test', `tests
add(`discard_output_stream', `hh', `cc')
add(`enum_iterator', `hh', `cc', `fwd', `test')
add(`exception', `hh', `cc')
+add(`executor', `hh', `cc', `fwd')
add(`extract_host_from_url', `hh', `cc', `fwd', `test')
add(`fast_unique_copy', `hh', `test')
add(`forward_parallel_for_each', `hh', `test')
diff --git a/src/clients/cave/cmd_sync.cc b/src/clients/cave/cmd_sync.cc
index e8220c0..56bcaf3 100644
--- a/src/clients/cave/cmd_sync.cc
+++ b/src/clients/cave/cmd_sync.cc
@@ -30,6 +30,7 @@
#include <paludis/util/condition_variable.hh>
#include <paludis/util/thread.hh>
#include <paludis/util/return_literal_function.hh>
+#include <paludis/util/executor.hh>
#include <paludis/output_manager.hh>
#include <paludis/repository.hh>
#include <paludis/environment.hh>
@@ -85,126 +86,6 @@ namespace
}
};
- std::string get_queue_name_func(
- const std::tr1::shared_ptr<const Environment> & env,
- const RepositoryName & r)
- {
- const std::tr1::shared_ptr<const Repository> repo(env->package_database()->fetch_repository(r));
- if (repo->sync_host_key())
- return repo->sync_host_key()->value();
- else
- return "(no host)";
- }
-
- struct Executive
- {
- virtual std::string queue_name() const = 0;
- virtual std::string unique_id() const = 0;
- virtual bool can_run() const = 0;
-
- virtual void pre_execute_exclusive() = 0;
- virtual void execute_threaded() = 0;
- virtual void post_execute_exclusive() = 0;
- };
-
- class Executor
- {
- private:
- int _pending;
- int _active;
- int _done;
-
- typedef std::multimap<std::string, std::tr1::shared_ptr<Executive> > Queues;
- typedef std::list<std::tr1::shared_ptr<Executive> > ReadyForPost;
- Queues _queues;
- ReadyForPost _ready_for_post;
- Mutex _mutex;
- ConditionVariable _condition;
-
- void _one(const std::tr1::shared_ptr<Executive> executive)
- {
- executive->execute_threaded();
-
- Lock lock(_mutex);
- _ready_for_post.push_back(executive);
- _condition.signal();
- }
-
- public:
- Executor() :
- _pending(0),
- _active(0),
- _done(0)
- {
- }
-
- int pending() const
- {
- return _pending;
- }
-
- int active() const
- {
- return _active;
- }
-
- int done() const
- {
- return _done;
- }
-
- void add(const std::tr1::shared_ptr<Executive> & x)
- {
- ++_pending;
- _queues.insert(std::make_pair(x->queue_name(), x));
- }
-
- void execute()
- {
- typedef std::map<std::string, std::tr1::shared_ptr<Thread> > Running;
- Running running;
-
- Lock lock(_mutex);
- while (true)
- {
- bool any(false);
- for (Queues::iterator q(_queues.begin()), q_end(_queues.end()) ;
- q != q_end ; )
- {
- if ((running.end() != running.find(q->first)) || ! q->second->can_run())
- {
- ++q;
- continue;
- }
-
- ++_active;
- --_pending;
- q->second->pre_execute_exclusive();
- running.insert(std::make_pair(q->first, make_shared_ptr(new Thread(
- std::tr1::bind(&Executor::_one, this, q->second)))));
- _queues.erase(q++);
- any = true;
- }
-
- if ((! any) && running.empty())
- break;
-
- _condition.wait(_mutex);
-
- for (ReadyForPost::iterator p(_ready_for_post.begin()), p_end(_ready_for_post.end()) ;
- p != p_end ; ++p)
- {
- --_active;
- ++_done;
- running.erase((*p)->queue_name());
- (*p)->post_execute_exclusive();
- }
-
- _ready_for_post.clear();
- }
- }
- };
-
struct SyncExecutive :
Executive
{