commit
377e381037
@ -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,223 @@ |
||||
#ifndef _ROTOR_ |
||||
#define _ROTOT_ |
||||
|
||||
#include "asynco.hpp" |
||||
#include <chrono> |
||||
|
||||
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(); |
||||
} |
||||
|
||||
/**
|
||||
* Get the time in us from the epoch |
||||
*/ |
||||
|
||||
int64_t rtime_us() { |
||||
return chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now() |
||||
.time_since_epoch()) |
||||
.count(); |
||||
} |
||||
|
||||
/**
|
||||
* 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() { |
||||
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++; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
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) : |
||||
st(_asynco_engine.io_context, boost::asio::chrono::milliseconds(_time)), |
||||
_stop(false), |
||||
repeate(_repeate), |
||||
callback(_callback), |
||||
time(_time) { |
||||
|
||||
init(); |
||||
} |
||||
|
||||
/**
|
||||
* Stop timer |
||||
* The stop flag is set and timer remove it from the queue |
||||
*/ |
||||
void stop() { |
||||
_stop = true; |
||||
st.cancel(); |
||||
} |
||||
|
||||
/**
|
||||
* Run callback now |
||||
* Forces the callback function to run independently of the timer |
||||
*/ |
||||
void now() { |
||||
st.cancel(); |
||||
} |
||||
|
||||
/**
|
||||
* Get the number of times the timer callback was runned |
||||
*/ |
||||
uint64_t ticks() { |
||||
return _ticks; |
||||
} |
||||
|
||||
/**
|
||||
* The logic status of the timer stop state |
||||
*/ |
||||
bool stoped() { |
||||
return _stop; |
||||
} |
||||
|
||||
/**
|
||||
* The destructor stops the timer |
||||
*/ |
||||
~timer() { |
||||
stop(); |
||||
} |
||||
}; |
||||
|
||||
/**
|
||||
* Class interval for periodic execution of the callback in time in ms |
||||
*/ |
||||
class interval { |
||||
shared_ptr<timer> _timer; |
||||
|
||||
public: |
||||
/**
|
||||
* Constructor initializes a shared pointer of type timer |
||||
*/ |
||||
interval(function<void()> callback, uint64_t time) :
|
||||
_timer(make_shared<timer> (callback, time, true)) { |
||||
} |
||||
|
||||
/**
|
||||
* Stop interval |
||||
* The stop flag is set and interval remove it from the queue |
||||
*/ |
||||
void stop() { |
||||
_timer->stop(); |
||||
} |
||||
|
||||
/**
|
||||
* Run callback now |
||||
* Forces the callback function to run independently of the interval |
||||
*/ |
||||
void now() { |
||||
_timer->now(); |
||||
} |
||||
|
||||
/**
|
||||
* Get the number of times the interval callback was runned |
||||
*/ |
||||
uint64_t ticks() { |
||||
return _timer->ticks(); |
||||
} |
||||
|
||||
/**
|
||||
* The logic status of the interval stop state |
||||
*/ |
||||
bool stoped() { |
||||
return _timer->stoped(); |
||||
} |
||||
|
||||
/**
|
||||
* The destructor stops the interval |
||||
*/ |
||||
~interval() { |
||||
stop(); |
||||
} |
||||
}; |
||||
|
||||
/**
|
||||
* Class timeout for delayed callback execution in ms |
||||
*/ |
||||
class timeout { |
||||
shared_ptr<timer> _timer; |
||||
|
||||
public: |
||||
/**
|
||||
* Constructor initializes a shared pointer of type timer |
||||
*/ |
||||
timeout(function<void()> callback, uint64_t time) :
|
||||
_timer(make_shared<timer> (callback, time, false)) { |
||||
} |
||||
|
||||
/**
|
||||
* Stop timeout |
||||
* The stop flag is set and timeout remove it from the queue |
||||
*/ |
||||
void stop() { |
||||
_timer->stop(); |
||||
} |
||||
|
||||
/**
|
||||
* Run callback now |
||||
* Forces the callback function to run independently of the timeout |
||||
*/ |
||||
void now() { |
||||
_timer->now(); |
||||
} |
||||
|
||||
/**
|
||||
* Get the number of times the timeout callback was runned |
||||
*/ |
||||
bool expired() { |
||||
return bool(_timer->ticks()); |
||||
} |
||||
|
||||
/**
|
||||
* The logic status of the timeout stop state |
||||
*/ |
||||
bool stoped() { |
||||
return _timer->stoped(); |
||||
} |
||||
|
||||
/**
|
||||
* The destructor stops the timeout |
||||
*/ |
||||
~timeout() { |
||||
stop(); |
||||
} |
||||
|
||||
}; |
||||
|
||||
} |
||||
} |
||||
|
||||
#endif |
Loading…
Reference in new issue