Working scheduler - potentially thread-unsafe!

This commit is contained in:
momo5502 2019-01-20 21:21:15 +01:00
parent 85077ec512
commit 180af9d404
6 changed files with 115 additions and 11 deletions

View File

@ -13,18 +13,20 @@ namespace game
public: public:
context(); context();
chaiscript::ChaiScript* get_chai();
executer* get_executer(); executer* get_executer();
scheduler* get_scheduler(); scheduler* get_scheduler();
parameters* get_parameters(); parameters* get_parameters();
event_handler* get_event_handler(); event_handler* get_event_handler();
chaiscript::ChaiScript* get_chai();
private: private:
chaiscript::ChaiScript chai_;
executer executer_; executer executer_;
scheduler scheduler_; scheduler scheduler_;
parameters parameters_; parameters parameters_;
event_handler event_handler_; event_handler event_handler_;
chaiscript::ChaiScript chai_;
}; };
} }
} }

View File

@ -15,6 +15,11 @@ namespace game
chai->add(chaiscript::constructor<entity()>(), "entity"); chai->add(chaiscript::constructor<entity()>(), "entity");
chai->add(chaiscript::constructor<entity(const entity&)>(), "entity"); chai->add(chaiscript::constructor<entity(const entity&)>(), "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::get), "get");
chai->add(chaiscript::fun(&entity::set), "set"); chai->add(chaiscript::fun(&entity::set), "set");
@ -27,11 +32,6 @@ namespace game
return ent.on_notify(event, callback, false); return ent.on_notify(event, callback, false);
}), "onNotify"); }), "onNotify");
chai->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity&
{
return lhs = rhs;
}), "=");
chai->add(chaiscript::fun([context](const std::string& event, chai->add(chaiscript::fun([context](const std::string& event,
const std::function<void(const entity&, const std::function<void(const entity&,
const std::vector<chaiscript:: const std::vector<chaiscript::

View File

@ -7,11 +7,86 @@ namespace game
{ {
scheduler::scheduler(context* context) : context_(context) scheduler::scheduler(context* context) : context_(context)
{ {
const auto chai = this->context_->get_chai();
chai->add(chaiscript::user_type<task_handle>(), "task_handle");
chai->add(chaiscript::constructor<task_handle()>(), "task_handle");
chai->add(chaiscript::constructor<task_handle(const task_handle&)>(), "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<void()>& callback, const long long milliseconds) -> task_handle
{
return this->add(callback, milliseconds, true);
}), "setTimeout");
chai->add(chaiscript::fun([this](const std::function<void()>& 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() 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<void()>& 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<void()>& 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;
}
}
} }
} }
} }

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "utils/chain.hpp"
namespace game namespace game
{ {
@ -6,6 +7,21 @@ namespace game
{ {
class context; 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<void()> callback;
std::chrono::milliseconds delay;
bool is_volatile;
};
class scheduler final class scheduler final
{ {
public: public:
@ -15,6 +31,14 @@ namespace game
private: private:
context* context_; context* context_;
utils::chain<task> tasks_;
std::atomic_int64_t current_task_id_ = 0;
task_handle add(const std::function<void()>& callback, long long milliseconds, bool is_volatile);
task_handle add(const std::function<void()>& callback, std::chrono::milliseconds delay, bool is_volatile);
void remove(const task_handle& handle);
}; };
} }
} }

View File

@ -35,6 +35,7 @@
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include <regex> #include <regex>
#include <chrono>
#include <thread> #include <thread>
#include <fstream> #include <fstream>
#include <utility> #include <utility>

View File

@ -1,10 +1,12 @@
#pragma once
namespace utils namespace utils
{ {
template <typename T> template <typename T>
class chain class chain final
{ {
public: public:
class entry class entry final
{ {
private: private:
std::shared_ptr<T> object_; std::shared_ptr<T> object_;
@ -23,7 +25,7 @@ namespace utils
void set(T object) void set(T object)
{ {
this->object_ = std::shared_ptr<T>(new T()); this->object_ = std::make_shared<T>();
*this->object_.get() = object; *this->object_.get() = object;
} }
@ -85,7 +87,7 @@ namespace utils
if (!this->empty()) if (!this->empty())
{ {
// Create new chain entry // Create new chain entry
std::shared_ptr<entry> current_object = std::shared_ptr<entry>(new entry); std::shared_ptr<entry> current_object = std::make_shared<entry>();
*current_object.get() = this->object_; *current_object.get() = this->object_;
// Add it to the chain // Add it to the chain