Compare commits
18 Commits
dev-own-en
...
dev
Author | SHA1 | Date |
---|---|---|
marcelb | 5b0e363cd5 | 2 weeks ago |
marcelb | 78501b0c9b | 2 weeks ago |
mbandic | 3fc313a9b5 | 3 weeks ago |
marcelb | 9e773f55c9 | 1 month ago |
mbandic | 1ccac9dbf8 | 1 month ago |
mbandic | 4f674467d2 | 1 month ago |
mbandic | 8b23bd6728 | 1 month ago |
mbandic | 2876372552 | 1 month ago |
mbandic | 7bf7a7d090 | 1 month ago |
marcelb | d8e0d0b49d | 2 months ago |
mbandic | 0b94c1e86c | 2 months ago |
mbandic | e3eddf006b | 7 months ago |
marcelb | 22dbfe89f1 | 7 months ago |
marcelb | e91c7f646d | 7 months ago |
marcelb | 377e381037 | 7 months ago |
marcelb | e4fbabd530 | 8 months ago |
marcelb | 14663d631a | 8 months ago |
mbandic | 35ff6bef4b | 8 months ago |
@ -1,2 +1,3 @@ |
|||||||
test/test |
test/test |
||||||
test/*.txt |
test/*.txt |
||||||
|
example |
@ -0,0 +1,19 @@ |
|||||||
|
#ifndef _ASYNCO_DEFINE_ |
||||||
|
#define _ASYNCO_DEFINE_ |
||||||
|
|
||||||
|
namespace marcelb { |
||||||
|
namespace asynco { |
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative names of functions - mostly for the sake of more beautiful coloring of the code |
||||||
|
*/ |
||||||
|
|
||||||
|
#define async_ marcelb::asynco::async_ |
||||||
|
#define await_ marcelb::asynco::await_ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,71 @@ |
|||||||
|
#ifndef _ASYNCO_ENGINE_ |
||||||
|
#define _ASYNCO_ENGINE_ |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
#include <memory> |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
#include <boost/asio.hpp> |
||||||
|
|
||||||
|
namespace marcelb { |
||||||
|
namespace asynco { |
||||||
|
|
||||||
|
#define HW_CONCURRENCY_MINIMAL 4 |
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal anonymous class for initializing the ASIO context and thread pool |
||||||
|
* !!! It is anonymous to protect against use in the initialization of other objects of the same type !!! |
||||||
|
*/ |
||||||
|
class Engine { |
||||||
|
public: |
||||||
|
boost::asio::io_context io_context; |
||||||
|
|
||||||
|
void run() { |
||||||
|
for (auto& runner : runners) { |
||||||
|
runner.join(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
|
||||||
|
unique_ptr<boost::asio::io_service::work> work { [&] () { |
||||||
|
return new boost::asio::io_service::work(io_context); |
||||||
|
} ()}; |
||||||
|
|
||||||
|
vector<thread> runners { [&] () { |
||||||
|
vector<thread> _runs; |
||||||
|
unsigned int num_of_runners; |
||||||
|
#ifdef NUM_OF_RUNNERS |
||||||
|
num_of_runners = NUM_OF_RUNNERS; |
||||||
|
#else |
||||||
|
num_of_runners = thread::hardware_concurrency(); |
||||||
|
if (num_of_runners < HW_CONCURRENCY_MINIMAL) { |
||||||
|
num_of_runners = HW_CONCURRENCY_MINIMAL; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
for (int i=0; i<num_of_runners; i++) { |
||||||
|
_runs.push_back(thread ( [this] () { |
||||||
|
io_context.run(); |
||||||
|
})); |
||||||
|
} |
||||||
|
|
||||||
|
return _runs; |
||||||
|
} ()}; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
extern Engine _asynco_engine; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,66 +0,0 @@ |
|||||||
#ifndef _EVENT_ |
|
||||||
#define _EVENT_ |
|
||||||
|
|
||||||
#include <iostream> |
|
||||||
#include <map> |
|
||||||
#include <vector> |
|
||||||
#include <string> |
|
||||||
#include <functional> |
|
||||||
#include "runner.hpp" |
|
||||||
|
|
||||||
using namespace std; |
|
||||||
|
|
||||||
namespace marcelb { |
|
||||||
namespace asynco { |
|
||||||
namespace events { |
|
||||||
|
|
||||||
/**
|
|
||||||
* Event class, for event-driven programming. |
|
||||||
* These events are typed according to the arguments of the callback function |
|
||||||
*/ |
|
||||||
template<typename... T> |
|
||||||
class event { |
|
||||||
private: |
|
||||||
mutex m_eve; |
|
||||||
unordered_map<string, vector<function<void(T...)>>> events; |
|
||||||
|
|
||||||
public: |
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines event by key, and callback function |
|
||||||
*/ |
|
||||||
void on(const string& key, function<void(T...)> callback) { |
|
||||||
lock_guard _off(m_eve); |
|
||||||
events[key].push_back(callback); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* It emits an event and sends a callback function saved according to the key with the passed parameters |
|
||||||
*/ |
|
||||||
template<typename... Args> |
|
||||||
void emit(const string& key, Args... args) { |
|
||||||
auto it_eve = events.find(key); |
|
||||||
if (it_eve != events.end()) { |
|
||||||
for (uint i =0; i<it_eve->second.size(); i++) { |
|
||||||
auto callback = bind(it_eve->second[i], forward<Args>(args)...);
|
|
||||||
_asyncon.put_task(callback); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an event listener from an event |
|
||||||
*/ |
|
||||||
void off(const string& key) { |
|
||||||
lock_guard _off(m_eve); |
|
||||||
events.erase(key); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endif |
|
@ -1,239 +0,0 @@ |
|||||||
#ifndef _ROTOR_ |
|
||||||
#define _ROTOT_ |
|
||||||
|
|
||||||
#include "runner.hpp" |
|
||||||
#include "chrono" |
|
||||||
#include <memory> |
|
||||||
|
|
||||||
#include "iostream" |
|
||||||
|
|
||||||
using namespace std; |
|
||||||
using namespace marcelb; |
|
||||||
using namespace asynco; |
|
||||||
|
|
||||||
namespace marcelb { |
|
||||||
namespace asynco { |
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the time in ms from the epoch |
|
||||||
*/ |
|
||||||
|
|
||||||
int64_t rtime_ms() { |
|
||||||
return chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() |
|
||||||
.time_since_epoch()) |
|
||||||
.count(); |
|
||||||
} |
|
||||||
|
|
||||||
int64_t rtime_us() { |
|
||||||
return chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now() |
|
||||||
.time_since_epoch()) |
|
||||||
.count(); |
|
||||||
} |
|
||||||
|
|
||||||
namespace { |
|
||||||
|
|
||||||
/**
|
|
||||||
* Intern class for timer async loop |
|
||||||
*/ |
|
||||||
class timer_core { |
|
||||||
public: |
|
||||||
mutex hangon; |
|
||||||
condition_variable cv; |
|
||||||
function<void()> callback; |
|
||||||
int64_t time; |
|
||||||
int64_t next; |
|
||||||
bool repeat; |
|
||||||
bool stop; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer constructor, receives a callback function and time |
|
||||||
*/ |
|
||||||
timer_core( function<void()> _callback, int64_t _time, bool _repeat): |
|
||||||
callback(_callback), time(_time*1000), repeat(_repeat), stop(false) { |
|
||||||
next = rtime_us() + time; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop timer |
|
||||||
*/ |
|
||||||
void clear() { |
|
||||||
// lock_guard<mutex> hang(hangon);
|
|
||||||
stop = true; |
|
||||||
cv.notify_one(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Destruktor of timer, call stop |
|
||||||
*/ |
|
||||||
~timer_core() { |
|
||||||
clear(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Event loop for time events |
|
||||||
*/ |
|
||||||
|
|
||||||
class rotor { |
|
||||||
vector<shared_ptr<timer_core>> tcores; |
|
||||||
mutex te_m; |
|
||||||
bool rotating = true; |
|
||||||
int64_t sampling; |
|
||||||
|
|
||||||
condition_variable te_cv; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Loop method, started by the constructor in a separate runner |
|
||||||
* It checks the events on the stack and sends the expired ones to the runner |
|
||||||
*/ |
|
||||||
void loop() { |
|
||||||
while (rotating) { |
|
||||||
vector<shared_ptr<timer_core>>::iterator next_tc; |
|
||||||
shared_ptr<timer_core> next_ptr; |
|
||||||
|
|
||||||
{ |
|
||||||
unique_lock<mutex> te_l(te_m); |
|
||||||
te_cv.wait(te_l, [this]{ return !tcores.empty() || rotating; }); |
|
||||||
if (!rotating) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
next_tc = min_element( tcores.begin(), tcores.end(), |
|
||||||
[](shared_ptr<timer_core> a, shared_ptr<timer_core> b ) { |
|
||||||
return a->next < b->next; |
|
||||||
} |
|
||||||
); |
|
||||||
|
|
||||||
next_ptr = *next_tc; |
|
||||||
} |
|
||||||
|
|
||||||
unique_lock<mutex> next_l(next_ptr->hangon); |
|
||||||
next_ptr->cv.wait_for(next_l, chrono::microseconds(next_ptr->next - rtime_us()), [&next_ptr] () { |
|
||||||
return next_ptr->stop; |
|
||||||
}); |
|
||||||
|
|
||||||
if (next_ptr->stop) { |
|
||||||
remove(next_tc); |
|
||||||
} else { |
|
||||||
_asyncon.put_task(next_ptr->callback); |
|
||||||
if (next_ptr->repeat) { |
|
||||||
next_ptr->next += next_ptr->time; |
|
||||||
} |
|
||||||
else { |
|
||||||
remove(next_tc); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
}
|
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* The method deletes a non-repeating or stopped event from the stack |
|
||||||
*/ |
|
||||||
void remove(vector<shared_ptr<timer_core>>::iterator it) { |
|
||||||
lock_guard<mutex> lock(te_m); |
|
||||||
tcores.erase(it); |
|
||||||
// te_cv.notify_one();
|
|
||||||
} |
|
||||||
|
|
||||||
public: |
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the rotor, starts the given loop by occupying one runner |
|
||||||
*/ |
|
||||||
rotor() { |
|
||||||
_asyncon.put_task( [&] () { |
|
||||||
loop(); |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a time event to the stack |
|
||||||
*/ |
|
||||||
void insert(shared_ptr<timer_core> tcore) { |
|
||||||
lock_guard<mutex> lock(te_m); |
|
||||||
tcores.push_back(tcore); |
|
||||||
te_cv.notify_one(); |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of active events |
|
||||||
*/ |
|
||||||
int active() { |
|
||||||
return tcores.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops all active events and stops the rotor |
|
||||||
*/ |
|
||||||
~rotor() { |
|
||||||
for (int i=0; i<tcores.size(); i++) { |
|
||||||
tcores[i]->clear(); |
|
||||||
} |
|
||||||
rotating = false; |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It is intended that there is only one global declaration |
|
||||||
*/ |
|
||||||
static rotor _rotor; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Core class for pure async timer functions |
|
||||||
*/ |
|
||||||
|
|
||||||
class _timer_intern { |
|
||||||
shared_ptr<timer_core> tcore; |
|
||||||
public: |
|
||||||
|
|
||||||
_timer_intern(function<void()> _callback, int64_t _time, bool repeat) { |
|
||||||
tcore = make_shared<timer_core>(_callback, _time, repeat); |
|
||||||
_rotor.insert(tcore); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop interval |
|
||||||
*/ |
|
||||||
void clear() { |
|
||||||
tcore->clear(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Class interval for periodic execution of the callback in time in ms |
|
||||||
*/ |
|
||||||
class interval : public _timer_intern { |
|
||||||
public: |
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor receives a callback function and an interval time |
|
||||||
*/ |
|
||||||
interval( function<void()> _callback, int64_t _time): |
|
||||||
_timer_intern(_callback, _time, true) { |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Class interval for delayed callback execution in ms |
|
||||||
*/ |
|
||||||
class timeout : public _timer_intern { |
|
||||||
public: |
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor receives a callback function and a delay time |
|
||||||
*/ |
|
||||||
timeout( function<void()> _callback, int64_t delay): |
|
||||||
_timer_intern(_callback, delay, false) { |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endif |
|
@ -1,136 +0,0 @@ |
|||||||
#ifndef _RUNNER_ |
|
||||||
#define _RUNNER_ |
|
||||||
|
|
||||||
#include <thread> |
|
||||||
#include <vector> |
|
||||||
#include <queue> |
|
||||||
#include <functional> |
|
||||||
#include <mutex> |
|
||||||
#include <condition_variable> |
|
||||||
#include <future> |
|
||||||
|
|
||||||
using namespace std; |
|
||||||
|
|
||||||
namespace marcelb { |
|
||||||
namespace asynco { |
|
||||||
|
|
||||||
#define HW_CONCURRENCY_MINIMAL 4 |
|
||||||
|
|
||||||
/**
|
|
||||||
* The runner class implements multithread, task stack and event loop for asynchronous execution of tasks |
|
||||||
*/ |
|
||||||
class runner { |
|
||||||
private: |
|
||||||
vector<thread> runners; |
|
||||||
queue<function<void()>> tasks; |
|
||||||
mutex q_io; |
|
||||||
condition_variable cv; |
|
||||||
bool stop; |
|
||||||
|
|
||||||
public: |
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor starts as many threads as the system has cores,
|
|
||||||
* and runs an event loop inside each one.
|
|
||||||
* Each event loop waits for tasks from the stack and executes them. |
|
||||||
*/ |
|
||||||
runner(unsigned int _num_of_runners = 0) : stop(false) { |
|
||||||
unsigned int num_of_runners = _num_of_runners; |
|
||||||
|
|
||||||
if (num_of_runners == 0) { |
|
||||||
#ifdef NUM_OF_RUNNERS |
|
||||||
num_of_runners = NUM_OF_RUNNERS; |
|
||||||
#else |
|
||||||
num_of_runners = thread::hardware_concurrency(); |
|
||||||
if (num_of_runners < HW_CONCURRENCY_MINIMAL) { |
|
||||||
num_of_runners = HW_CONCURRENCY_MINIMAL; |
|
||||||
} |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
for (size_t i = 0; i < num_of_runners; ++i) { |
|
||||||
runners.emplace_back( thread([&] { |
|
||||||
while (!stop) { |
|
||||||
function<void()> task; |
|
||||||
{ |
|
||||||
unique_lock<mutex> lock(q_io); |
|
||||||
cv.wait(lock, [this] { return stop || !tasks.empty(); }); |
|
||||||
// if (stop && tasks.empty())
|
|
||||||
if (stop) |
|
||||||
return; |
|
||||||
task = move(tasks.front()); |
|
||||||
tasks.pop(); |
|
||||||
} |
|
||||||
task(); |
|
||||||
} |
|
||||||
})); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* With the method, we send the callback function and its arguments to the task stack |
|
||||||
*/ |
|
||||||
template<class F, class... Args> |
|
||||||
auto put_task(F&& f, Args&&... args) |
|
||||||
-> future<typename result_of<F(Args...)>::type> { |
|
||||||
using return_type = typename result_of<F(Args...)>::type; |
|
||||||
|
|
||||||
auto task = make_shared<packaged_task<return_type()>>(bind(forward<F>(f), forward<Args>(args)...)); |
|
||||||
future<return_type> res = task->get_future(); |
|
||||||
{ |
|
||||||
unique_lock<mutex> lock(q_io); |
|
||||||
|
|
||||||
if (stop) { |
|
||||||
throw runtime_error("Pool is stoped!"); |
|
||||||
} |
|
||||||
|
|
||||||
tasks.emplace([task]() { (*task)(); }); |
|
||||||
} |
|
||||||
|
|
||||||
cv.notify_one(); |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of tasks the runner has to perform |
|
||||||
*/ |
|
||||||
unsigned int count_tasks() { |
|
||||||
return tasks.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of threads used by the runner |
|
||||||
*/ |
|
||||||
unsigned int count_threads() { |
|
||||||
return runners.size(); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* The destructor stops all loops and stops all threads |
|
||||||
*/ |
|
||||||
~runner() { |
|
||||||
{ |
|
||||||
unique_lock<mutex> lock(q_io); |
|
||||||
stop = true; |
|
||||||
} |
|
||||||
cv.notify_all(); |
|
||||||
for (thread& runner : runners) { |
|
||||||
runner.join(); |
|
||||||
} |
|
||||||
runners.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal global library variable |
|
||||||
*/ |
|
||||||
static runner _asyncon; |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#endif |
|
@ -0,0 +1,161 @@ |
|||||||
|
#ifndef _ASYNCO_TIMERS_ |
||||||
|
#define _ASYNCO_TIMERS_ |
||||||
|
|
||||||
|
#include <chrono> |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
#include "asynco.hpp" |
||||||
|
|
||||||
|
namespace marcelb { |
||||||
|
namespace asynco { |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time in ms from the epoch |
||||||
|
*/ |
||||||
|
|
||||||
|
int64_t rtime_ms(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time in us from the epoch |
||||||
|
*/ |
||||||
|
|
||||||
|
int64_t rtime_us(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Core timer class for construct time async functions |
||||||
|
*/ |
||||||
|
class timer { |
||||||
|
boost::asio::steady_timer st; |
||||||
|
bool _stop = false; |
||||||
|
bool repeate; |
||||||
|
function<void()> callback; |
||||||
|
uint64_t time; |
||||||
|
uint64_t _ticks = 0; |
||||||
|
|
||||||
|
/**
|
||||||
|
* A method to assign a callback wrapper and a reinitialization algorithm |
||||||
|
*/ |
||||||
|
void init(); |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor creates the steady_timer and accompanying variables and runs a method to initialize the timer |
||||||
|
*/ |
||||||
|
timer (function<void()> _callback, uint64_t _time, bool _repeate); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop timer |
||||||
|
* The stop flag is set and timer remove it from the queue |
||||||
|
*/ |
||||||
|
void stop(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Run callback now |
||||||
|
* Forces the callback function to run independently of the timer |
||||||
|
*/ |
||||||
|
void now(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of times the timer callback was runned |
||||||
|
*/ |
||||||
|
uint64_t ticks(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* The logic status of the timer stop state |
||||||
|
*/ |
||||||
|
bool stoped(); |
||||||
|
/**
|
||||||
|
* The destructor stops the timer |
||||||
|
*/ |
||||||
|
~timer(); |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Class periodic for periodic execution of the callback in time in ms |
||||||
|
*/ |
||||||
|
class periodic { |
||||||
|
shared_ptr<timer> _timer; |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor initializes a shared pointer of type timer |
||||||
|
*/ |
||||||
|
periodic(function<void()> callback, uint64_t time); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop periodic |
||||||
|
* The stop flag is set and periodic remove it from the queue |
||||||
|
*/ |
||||||
|
void stop(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Run callback now |
||||||
|
* Forces the callback function to run independently of the periodic |
||||||
|
*/ |
||||||
|
void now(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of times the periodic callback was runned |
||||||
|
*/ |
||||||
|
uint64_t ticks(); |
||||||
|
/**
|
||||||
|
* The logic status of the periodic stop state |
||||||
|
*/ |
||||||
|
bool stoped(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* The destructor stops the periodic |
||||||
|
*/ |
||||||
|
~periodic(); |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Class delayed for delayed callback execution in ms |
||||||
|
*/ |
||||||
|
class delayed { |
||||||
|
shared_ptr<timer> _timer; |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor initializes a shared pointer of type timer |
||||||
|
*/ |
||||||
|
delayed(function<void()> callback, uint64_t time); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop delayed |
||||||
|
* The stop flag is set and delayed remove it from the queue |
||||||
|
*/ |
||||||
|
void stop(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Run callback now |
||||||
|
* Forces the callback function to run independently of the delayed |
||||||
|
*/ |
||||||
|
void now(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get is the delayed callback runned |
||||||
|
*/ |
||||||
|
bool expired(); |
||||||
|
/**
|
||||||
|
* The logic status of the delayed stop state |
||||||
|
*/ |
||||||
|
bool stoped(); |
||||||
|
/**
|
||||||
|
* The destructor stops the delayed |
||||||
|
*/ |
||||||
|
~delayed(); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
shared_ptr<periodic> Periodic(function<void()> callback, uint64_t time); |
||||||
|
shared_ptr<delayed> Delayed(function<void()> callback, uint64_t time); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,92 @@ |
|||||||
|
#ifndef _ASYNCO_TRIGGER_ |
||||||
|
#define _ASYNCO_TRIGGER_ |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <vector> |
||||||
|
#include <string> |
||||||
|
#include <functional> |
||||||
|
|
||||||
|
using namespace std; |
||||||
|
|
||||||
|
#include "engine.hpp" |
||||||
|
namespace marcelb { |
||||||
|
namespace asynco { |
||||||
|
namespace triggers { |
||||||
|
|
||||||
|
/**
|
||||||
|
* trigger class, for event-driven programming. |
||||||
|
* These events are typed according to the arguments of the callback function |
||||||
|
*/ |
||||||
|
template<typename... T> |
||||||
|
class trigger { |
||||||
|
private: |
||||||
|
mutex m_eve; |
||||||
|
unordered_map<string, vector<function<void(T...)>>> triggers; |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines event by key, and callback function |
||||||
|
*/ |
||||||
|
void on(const string& key, function<void(T...)> callback) { |
||||||
|
lock_guard _off(m_eve); |
||||||
|
triggers[key].push_back(callback); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* It emits an event and sends a callback function saved according to the key with the passed parameters |
||||||
|
*/ |
||||||
|
template<typename... Args> |
||||||
|
void tick(const string& key, Args... args) { |
||||||
|
auto it_eve = triggers.find(key); |
||||||
|
if (it_eve != triggers.end()) { |
||||||
|
for (uint i =0; i<it_eve->second.size(); i++) { |
||||||
|
auto callback = bind(it_eve->second[i], forward<Args>(args)...);
|
||||||
|
asynco::async_(callback); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an trigger listener from an event |
||||||
|
*/ |
||||||
|
void off(const string& key) { |
||||||
|
lock_guard _off(m_eve); |
||||||
|
triggers.erase(key); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all trigger listener |
||||||
|
*/ |
||||||
|
void off() { |
||||||
|
lock_guard _off(m_eve); |
||||||
|
triggers.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get num of listeners by an trigger key |
||||||
|
*/ |
||||||
|
unsigned int listeners(const string& key) { |
||||||
|
return triggers[key].size(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get num of all listeners |
||||||
|
*/ |
||||||
|
unsigned int listeners() { |
||||||
|
unsigned int listeners = 0; |
||||||
|
for (auto& ev : triggers) { |
||||||
|
listeners += ev.second.size(); |
||||||
|
} |
||||||
|
return listeners; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,7 @@ |
|||||||
|
#include "../lib/engine.hpp" |
||||||
|
|
||||||
|
namespace marcelb::asynco { |
||||||
|
|
||||||
|
Engine _asynco_engine; |
||||||
|
|
||||||
|
}; |
@ -0,0 +1,145 @@ |
|||||||
|
#include "../lib/timers.hpp" |
||||||
|
|
||||||
|
namespace marcelb::asynco { |
||||||
|
|
||||||
|
int64_t rtime_ms() { |
||||||
|
return chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() |
||||||
|
.time_since_epoch()) |
||||||
|
.count(); |
||||||
|
} |
||||||
|
|
||||||
|
int64_t rtime_us() { |
||||||
|
return chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now() |
||||||
|
.time_since_epoch()) |
||||||
|
.count(); |
||||||
|
} |
||||||
|
|
||||||
|
void timer::init() { |
||||||
|
st.async_wait( [this] (const boost::system::error_code&) { |
||||||
|
if (!_stop) { |
||||||
|
callback(); |
||||||
|
if (repeate) { |
||||||
|
st = boost::asio::steady_timer(_asynco_engine.io_context, boost::asio::chrono::milliseconds(time)); |
||||||
|
init(); |
||||||
|
} |
||||||
|
_ticks++; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
timer::timer (function<void()> _callback, uint64_t _time, bool _repeate) : |
||||||
|
st(_asynco_engine.io_context, boost::asio::chrono::milliseconds(_time)), |
||||||
|
_stop(false), |
||||||
|
repeate(_repeate), |
||||||
|
callback(_callback), |
||||||
|
time(_time) { |
||||||
|
|
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
void timer::stop() { |
||||||
|
_stop = true; |
||||||
|
st.cancel(); |
||||||
|
} |
||||||
|
|
||||||
|
void timer::now() { |
||||||
|
st.cancel(); |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t timer::ticks() { |
||||||
|
return _ticks; |
||||||
|
} |
||||||
|
|
||||||
|
bool timer::stoped() { |
||||||
|
return _stop; |
||||||
|
} |
||||||
|
|
||||||
|
timer::~timer() { |
||||||
|
stop(); |
||||||
|
} |
||||||
|
|
||||||
|
periodic::periodic(function<void()> callback, uint64_t time) :
|
||||||
|
_timer(make_shared<timer> (callback, time, true)) { |
||||||
|
} |
||||||
|
|
||||||
|
void periodic::stop() { |
||||||
|
_timer->stop(); |
||||||
|
} |
||||||
|
|
||||||
|
void periodic::now() { |
||||||
|
_timer->now(); |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t periodic::ticks() { |
||||||
|
return _timer->ticks(); |
||||||
|
} |
||||||
|
|
||||||
|
bool periodic::stoped() { |
||||||
|
return _timer->stoped(); |
||||||
|
} |
||||||
|
|
||||||
|
periodic::~periodic() { |
||||||
|
stop(); |
||||||
|
} |
||||||
|
|
||||||
|
delayed::delayed(function<void()> callback, uint64_t time) :
|
||||||
|
_timer(make_shared<timer> (callback, time, false)) { |
||||||
|
} |
||||||
|
|
||||||
|
void delayed::stop() { |
||||||
|
_timer->stop(); |
||||||
|
} |
||||||
|
|
||||||
|
void delayed::now() { |
||||||
|
_timer->now(); |
||||||
|
} |
||||||
|
|
||||||
|
bool delayed::expired() { |
||||||
|
return bool(_timer->ticks()); |
||||||
|
} |
||||||
|
|
||||||
|
bool delayed::stoped() { |
||||||
|
return _timer->stoped(); |
||||||
|
} |
||||||
|
|
||||||
|
delayed::~delayed() { |
||||||
|
stop(); |
||||||
|
} |
||||||
|
|
||||||
|
mutex p_io, d_io; |
||||||
|
vector<shared_ptr<periodic>> periodic_calls_container; |
||||||
|
vector<shared_ptr<delayed>> delayed_calls_container; |
||||||
|
|
||||||
|
shared_ptr<periodic> Periodic(function<void()> callback, uint64_t time) { |
||||||
|
shared_ptr<periodic> periodic_ptr(make_shared<periodic>(callback, time)); |
||||||
|
async_ ( [&, periodic_ptr](){ |
||||||
|
lock_guard<mutex> lock(p_io); |
||||||
|
periodic_calls_container.push_back(periodic_ptr); |
||||||
|
for (uint32_t i=0; i<periodic_calls_container.size(); i++) { |
||||||
|
if (periodic_calls_container[i]->stoped()) { |
||||||
|
periodic_calls_container.erase(periodic_calls_container.begin()+i); |
||||||
|
i--; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
return periodic_ptr; |
||||||
|
} |
||||||
|
|
||||||
|
shared_ptr<delayed> Delayed(function<void()> callback, uint64_t time) { |
||||||
|
shared_ptr<delayed> delayed_ptr(make_shared<delayed>(callback, time)); |
||||||
|
async_ ( [&, delayed_ptr](){ |
||||||
|
lock_guard<mutex> lock(p_io); |
||||||
|
delayed_calls_container.push_back(delayed_ptr); |
||||||
|
for (uint32_t i=0; i<delayed_calls_container.size(); i++) { |
||||||
|
if (delayed_calls_container[i]->stoped() || delayed_calls_container[i]->expired()) { |
||||||
|
delayed_calls_container.erase(delayed_calls_container.begin()+i); |
||||||
|
i--; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
return delayed_ptr; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}; |
@ -0,0 +1 @@ |
|||||||
|
g++ test.cpp ../src/* -o test |
Loading…
Reference in new issue