From 180af9d404400e0163a1c2cce9a7756c548492ea Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 20 Jan 2019 21:21:15 +0100 Subject: [PATCH] Working scheduler - potentially thread-unsafe! --- src/game/scripting/context.hpp | 6 +- src/game/scripting/context_initializer.cpp | 10 +-- src/game/scripting/scheduler.cpp | 75 ++++++++++++++++++++++ src/game/scripting/scheduler.hpp | 24 +++++++ src/std_include.hpp | 1 + src/utils/chain.hpp | 10 +-- 6 files changed, 115 insertions(+), 11 deletions(-) diff --git a/src/game/scripting/context.hpp b/src/game/scripting/context.hpp index ee46c19..56cd620 100644 --- a/src/game/scripting/context.hpp +++ b/src/game/scripting/context.hpp @@ -13,18 +13,20 @@ namespace game public: context(); + chaiscript::ChaiScript* get_chai(); + executer* get_executer(); scheduler* get_scheduler(); parameters* get_parameters(); event_handler* get_event_handler(); - chaiscript::ChaiScript* get_chai(); private: + chaiscript::ChaiScript chai_; + executer executer_; scheduler scheduler_; parameters parameters_; event_handler event_handler_; - chaiscript::ChaiScript chai_; }; } } diff --git a/src/game/scripting/context_initializer.cpp b/src/game/scripting/context_initializer.cpp index 6e31317..3c57eec 100644 --- a/src/game/scripting/context_initializer.cpp +++ b/src/game/scripting/context_initializer.cpp @@ -15,6 +15,11 @@ namespace game chai->add(chaiscript::constructor(), "entity"); chai->add(chaiscript::constructor(), "entity"); + chai->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity& + { + return lhs = rhs; + }), "="); + chai->add(chaiscript::fun(&entity::get), "get"); chai->add(chaiscript::fun(&entity::set), "set"); @@ -27,11 +32,6 @@ namespace game return ent.on_notify(event, callback, false); }), "onNotify"); - chai->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity& - { - return lhs = rhs; - }), "="); - chai->add(chaiscript::fun([context](const std::string& event, const std::functioncontext_->get_chai(); + + chai->add(chaiscript::user_type(), "task_handle"); + chai->add(chaiscript::constructor(), "task_handle"); + chai->add(chaiscript::constructor(), "task_handle"); + + chai->add(chaiscript::fun([](task_handle& lhs, const task_handle& rhs) -> task_handle& + { + return lhs = rhs; + }), "="); + + chai->add(chaiscript::fun([this](const std::function& callback, const long long milliseconds) -> task_handle + { + return this->add(callback, milliseconds, true); + }), "setTimeout"); + + chai->add(chaiscript::fun([this](const std::function& callback, const long long milliseconds) -> task_handle + { + return this->add(callback, milliseconds, false); + }), "setInterval"); + + const auto clear = [this](const task_handle& handle) + { + this->remove(handle); + }; + + chai->add(chaiscript::fun(clear), "clear"); + chai->add(chaiscript::fun(clear), "clearTimeout"); + chai->add(chaiscript::fun(clear), "clearInterval"); } void scheduler::run_frame() { + for (auto task = this->tasks_.begin(); task.is_valid(); ++task) + { + const auto now = std::chrono::steady_clock::now(); + if ((now - task->last_execution) > task->delay) + { + task->last_execution = now; + if (task->is_volatile) + { + this->tasks_.remove(task); + } + task->callback(); + } + } + } + + task_handle scheduler::add(const std::function& callback, const long long milliseconds, + const bool is_volatile) + { + return this->add(callback, std::chrono::milliseconds(milliseconds), is_volatile); + } + + task_handle scheduler::add(const std::function& callback, const std::chrono::milliseconds delay, + const bool is_volatile) + { + task task; + task.is_volatile = is_volatile; + task.callback = callback; + task.delay = delay; + task.last_execution = std::chrono::steady_clock::now(); + task.id = ++this->current_task_id_; + + this->tasks_.add(task); + + return { task.id }; + } + + void scheduler::remove(const task_handle& handle) + { + for (auto task = this->tasks_.begin(); task.is_valid(); ++task) + { + if(task->id == handle.id) + { + this->tasks_.remove(task); + break; + } + } } } } diff --git a/src/game/scripting/scheduler.hpp b/src/game/scripting/scheduler.hpp index bc662d8..5141345 100644 --- a/src/game/scripting/scheduler.hpp +++ b/src/game/scripting/scheduler.hpp @@ -1,4 +1,5 @@ #pragma once +#include "utils/chain.hpp" namespace game { @@ -6,6 +7,21 @@ namespace game { class context; + class task_handle + { + public: + unsigned long long id = 0; + }; + + class task final : public task_handle + { + public: + std::chrono::steady_clock::time_point last_execution; + std::function callback; + std::chrono::milliseconds delay; + bool is_volatile; + }; + class scheduler final { public: @@ -15,6 +31,14 @@ namespace game private: context* context_; + + utils::chain tasks_; + std::atomic_int64_t current_task_id_ = 0; + + task_handle add(const std::function& callback, long long milliseconds, bool is_volatile); + task_handle add(const std::function& callback, std::chrono::milliseconds delay, bool is_volatile); + + void remove(const task_handle& handle); }; } } diff --git a/src/std_include.hpp b/src/std_include.hpp index e778e6f..e8bbfad 100644 --- a/src/std_include.hpp +++ b/src/std_include.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/src/utils/chain.hpp b/src/utils/chain.hpp index bb55bdc..8804c9d 100644 --- a/src/utils/chain.hpp +++ b/src/utils/chain.hpp @@ -1,10 +1,12 @@ +#pragma once + namespace utils { template - class chain + class chain final { public: - class entry + class entry final { private: std::shared_ptr object_; @@ -23,7 +25,7 @@ namespace utils void set(T object) { - this->object_ = std::shared_ptr(new T()); + this->object_ = std::make_shared(); *this->object_.get() = object; } @@ -85,7 +87,7 @@ namespace utils if (!this->empty()) { // Create new chain entry - std::shared_ptr current_object = std::shared_ptr(new entry); + std::shared_ptr current_object = std::make_shared(); *current_object.get() = this->object_; // Add it to the chain