summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2019-01-23 20:33:33 +0100
committerNao Pross <naopross@thearcway.org>2019-01-23 20:33:33 +0100
commitd0f35bf97063d1d786713f373e4753bed56d4f0b (patch)
tree19dc0f18ca966424b286b1cf1e4dd686f60eaa64
parentMerge branch 'raii-task' (diff)
downloadflatland-d0f35bf97063d1d786713f373e4753bed56d4f0b.tar.gz
flatland-d0f35bf97063d1d786713f373e4753bed56d4f0b.zip
Update job interface to allow safe ownership delegation
-rw-r--r--engine/include/core/priority.hpp15
-rw-r--r--engine/include/core/task.hpp24
-rw-r--r--engine/task.cpp7
-rw-r--r--test/task_test.cpp29
4 files changed, 43 insertions, 32 deletions
diff --git a/engine/include/core/priority.hpp b/engine/include/core/priority.hpp
index d6c9b35..ae4a6db 100644
--- a/engine/include/core/priority.hpp
+++ b/engine/include/core/priority.hpp
@@ -16,21 +16,16 @@ namespace flat {
};
class prioritized {
- private:
- const priority_t m_priority;
-
public:
- prioritized(priority_t priority = priority_t::none)
- : m_priority(priority) {}
+ const priority_t priority;
- const priority_t priority() const {
- return m_priority;
- }
+ prioritized(priority_t p = priority_t::none)
+ : priority(p) {}
};
struct prioritize {
bool operator()(const prioritized& lhs, const prioritized& rhs) {
- return lhs.priority() < rhs.priority();
+ return lhs.priority < rhs.priority;
}
bool operator()(const std::weak_ptr<prioritized> lhs, const std::weak_ptr<prioritized> rhs) {
@@ -38,7 +33,7 @@ namespace flat {
if (auto r = rhs.lock()) {
// if both valid, check their priority
// in case they are the same, left is prioritized
- return l->priority() < r->priority();
+ return l->priority < r->priority;
} else {
// if right is expired, left is prioritized
return true;
diff --git a/engine/include/core/task.hpp b/engine/include/core/task.hpp
index 570e547..77e1da6 100644
--- a/engine/include/core/task.hpp
+++ b/engine/include/core/task.hpp
@@ -2,7 +2,9 @@
#include "priority.hpp"
+#include <unordered_set>
#include <functional>
+#include <variant>
#include <memory>
namespace flat {
@@ -13,6 +15,7 @@ namespace flat {
class task : public prioritized {
public:
+ using ptr = std::shared_ptr<task>;
using callback = std::function<void(void)>;
task() = delete;
@@ -24,13 +27,24 @@ namespace flat {
callback m_callback;
};
- struct job : public queue<std::weak_ptr<task>> {
- std::shared_ptr<task> make_task(task::callback f, priority_t p = priority_t::none);
- void invoke_tasks();
+ class job : protected queue<std::weak_ptr<task>> {
+ public:
+ /// add a task function owned by the job object
+ void add_task(task::callback f, priority_t p);
+
+ /// add a task function not owned by the job object (weak_ptr)
+ std::shared_ptr<task> delegate_task(task::callback f, priority_t p = priority_t::none);
- inline void operator()() {
- invoke_tasks();
+ /// add a task methods not owned by the job object (weak_ptr),
+ /// this allows to make the task die when the owner object goes out of scope
+ template<typename R, typename T>
+ inline std::shared_ptr<task> delegate_task(R T::*mf, T& obj, priority_t p = priority_t::none) {
+ return delegate_task(std::bind(mf, obj), p);
}
+
+ /// run tasks
+ void invoke_tasks();
+ inline void operator()() { invoke_tasks(); }
};
}
}
diff --git a/engine/task.cpp b/engine/task.cpp
index 8950633..9cfbec4 100644
--- a/engine/task.cpp
+++ b/engine/task.cpp
@@ -16,14 +16,17 @@ namespace flat {
task::task(task::callback f, priority_t p)
: m_callback(f) {}
- std::shared_ptr<task> job::make_task(task::callback f, priority_t p) {
-
+ std::shared_ptr<task> job::delegate_task(task::callback f, priority_t p) {
auto shared = std::make_shared<task>(f, p);
insert(shared);
return shared;
}
+ void job::add_task(task::callback f, priority_t p) {
+ insert(std::make_shared<task>(f, p));
+ }
+
void job::invoke_tasks() {
// expired tasks to remove
std::vector<job::value_type> to_erase;
diff --git a/test/task_test.cpp b/test/task_test.cpp
index 76fb3b7..04bb23d 100644
--- a/test/task_test.cpp
+++ b/test/task_test.cpp
@@ -6,21 +6,19 @@
using namespace flat::core;
// test class
-struct message {
-
- message(job& m_job, bool date)
- {
- if (date)
- mytask = m_job.make_task(std::bind(&message::print_date, *this));
- else
- mytask = m_job.make_task(std::bind(&message::print_motd, *this));
- }
-
- std::shared_ptr<task> mytask;
+class message {
+private:
+ task::ptr mytask;
std::string motd = "today we have no motd!";
std::string date = "1 Jan 1970";
+public:
+ message(job& job) {
+ // add an example job
+ mytask = job.delegate_task(&message::print_motd, *this);
+ }
+
void print_date() {
std::cout << date << std::endl;
}
@@ -49,11 +47,11 @@ int main(int argc, char *argv[]) {
job f_job;
// test a function
- auto hello_fn_task = f_job.make_task(hello);
+ auto hello_fn_task = f_job.delegate_task(hello);
// test a function ad make the pointer go out of scope
{
- auto ciao_fn_task = f_job.make_task(ciao);
+ auto ciao_fn_task = f_job.delegate_task(ciao);
}
f_job();
@@ -61,14 +59,15 @@ int main(int argc, char *argv[]) {
std::cout << std::endl;
std::cout << "Testing methods" << std::endl;
std::cout << "should print once: today we have no motd!" << std::endl;
+
job m_job;
// test a method
- message m(m_job, false);
+ message m(m_job);
// test a method of an object that goes out of scope
{
- message out(m_job, true);
+ message out(m_job);
}
// invoke tasks