From 4d79b1459a02fa8e49787fe9fc316128ddff1885 Mon Sep 17 00:00:00 2001 From: mbandic Date: Wed, 27 Mar 2024 11:56:31 +0000 Subject: [PATCH] Much more precise timer functions --- lib/rotor.hpp | 88 ++++++++++++++++++------------------ test/test.cpp | 121 +++++++++++++++++++++++++------------------------- 2 files changed, 103 insertions(+), 106 deletions(-) diff --git a/lib/rotor.hpp b/lib/rotor.hpp index 4387038..2614580 100644 --- a/lib/rotor.hpp +++ b/lib/rotor.hpp @@ -38,9 +38,10 @@ namespace { class timer_core { public: mutex hangon; + condition_variable cv; function callback; - int64_t init; int64_t time; + int64_t next; bool repeat; bool stop; @@ -48,15 +49,17 @@ class timer_core { * Timer constructor, receives a callback function and time */ timer_core( function _callback, int64_t _time, bool _repeat): - callback(_callback), init(rtime_us()), time(_time*1000), repeat(_repeat), stop(false) { + callback(_callback), time(_time*1000), repeat(_repeat), stop(false) { + next = rtime_us() + time; } /** * Stop timer */ void clear() { - lock_guard hang(hangon); + // lock_guard hang(hangon); stop = true; + cv.notify_one(); } /** @@ -77,65 +80,58 @@ class rotor { 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) { - for (int i=0; i>::iterator next_tc; + shared_ptr next_ptr; + + { + unique_lock te_l(te_m); + te_cv.wait(te_l, [this]{ return !tcores.empty(); }); + // calc_next(); - if (tcores[i]->stop) { - remove(i); - i--; + next_tc = min_element( tcores.begin(), tcores.end(), + [](shared_ptr a, shared_ptr b ) { + return a->next < b->next; } + ); - else if (expired(tcores[i])) { - _asyncon.put_task(tcores[i]->callback); - if (tcores[i]->repeat) { - tcores[i]->init = rtime_us(); - } - else { - remove(i); - i--; - } + next_ptr = *next_tc; + } + + unique_lock 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); } } - this_thread::sleep_for(chrono::microseconds(sampling)); - } - } - /** - * The method checks whether the time event has expired - */ - bool expired(shared_ptr tcore) { - return rtime_us() - tcore->init >= tcore->time; + } } - + /** * The method deletes a non-repeating or stopped event from the stack */ - void remove(const int& position) { + void remove(vector>::iterator it) { lock_guard lock(te_m); - tcores.erase(tcores.begin()+position); - update_sampling(); - } - - /** - * Updates the idle time of the loop, according to twice the frequency of available events - */ - void update_sampling() { - if (tcores.empty()) { - sampling = 100; - return; - } - sampling = tcores[0]->time; - for (int i=0; i tcores[i]->time) { - sampling = tcores[i]->time; - } - } - sampling /= tcores.size()*2; + tcores.erase(it); + te_cv.notify_one(); } public: @@ -155,7 +151,7 @@ class rotor { void insert(shared_ptr tcore) { lock_guard lock(te_m); tcores.push_back(tcore); - update_sampling(); + te_cv.notify_one(); }; /** diff --git a/test/test.cpp b/test/test.cpp index 0c9984e..389cd88 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -61,11 +61,11 @@ int main () { auto start = rtime_ms(); - // // --------------- TIME ASYNCHRONOUS FUNCTIONS -------------- + // --------------- TIME ASYNCHRONOUS FUNCTIONS -------------- - // /** - // * Init interval and timeout; clear interval and timeout - // */ + /** + * Init interval and timeout; clear interval and timeout + */ // interval( [&] () { // cout << "interval 1: " << rtime_ms() - start << endl; @@ -88,17 +88,17 @@ int main () { // cout << "interval 4: " << rtime_ms() - start << endl; // }, 400); - // interval inter1 ([&]() { - // cout << "interval prvi " << rtime_ms() - start << endl; - // }, 1000); + interval inter1 ([&]() { + cout << "interval prvi " << rtime_ms() - start << endl; + }, 1000); - // interval inter2 ([&]() { - // cout << "interval drugi " << rtime_ms() - start << endl; - // }, 2000); + interval inter2 ([&]() { + cout << "interval drugi " << rtime_ms() - start << endl; + }, 2000); - // interval inter3 ([&]() { - // cout << "interval treći " << rtime_ms() - start << endl; - // }, 3000); + interval inter3 ([&]() { + cout << "interval treći " << rtime_ms() - start << endl; + }, 3000); // interval inter4 ([&]() { // cout << "interval cetvrti " << rtime_ms() - start << endl; @@ -114,17 +114,18 @@ int main () { // timeout time1 ( [&] () { // cout << "Close interval 1 i 2 " << rtime_ms() - start << endl; - // // inter1.clear(); + // inter1.clear(); // // cout << "inter1.stop " << inter1.stop << endl; - // // inter2.clear(); + // inter2.clear(); // // cout << "inter2.stop " << inter2.stop << endl; // }, 5000); + // timeout time2 ([&] () { // cout << "Close interval 3 " << rtime_ms() - start << endl; // // inter3.clear(); - // // time1.clear(); + // time1.clear(); // }, 2000); // // ------------------------ MAKE FUNCTIONS ASYNCHRONOUS ------------------------- @@ -218,68 +219,68 @@ int main () { // }); // }); - // --------------- EVENTS ------------------- + // // --------------- EVENTS ------------------- - /** - * initialization of typed events - */ + // /** + // * initialization of typed events + // */ - event ev2int; - event evintString; - event<> evoid; + // event ev2int; + // event evintString; + // event<> evoid; - ev2int.on("sum", [](int a, int b) { - cout << "Sum " << a+b << endl; - }); + // ev2int.on("sum", [](int a, int b) { + // cout << "Sum " << a+b << endl; + // }); - ev2int.on("sum", [](int a, int b) { - cout << "Sum done" << endl; - }); + // ev2int.on("sum", [](int a, int b) { + // cout << "Sum done" << endl; + // }); - evintString.on("substract", [](int a, string b) { - cout << "Substract " << a-stoi(b) << endl; - }); + // evintString.on("substract", [](int a, string b) { + // cout << "Substract " << a-stoi(b) << endl; + // }); - evoid.on("void", []() { - cout << "Void emited" << endl; - }); + // evoid.on("void", []() { + // cout << "Void emited" << endl; + // }); - string emited2 = "2"; + // string emited2 = "2"; - evoid.on("void", [&]() { - cout << "Void emited " << emited2 << endl; - }); + // evoid.on("void", [&]() { + // cout << "Void emited " << emited2 << endl; + // }); - evoid.emit("void"); - sleep(1); + // evoid.emit("void"); + // sleep(1); - /** - * Emit - */ + // /** + // * Emit + // */ - ev2int.emit("sum", 5, 8); + // ev2int.emit("sum", 5, 8); - sleep(1); - evintString.emit("substract", 3, to_string(2)); + // sleep(1); + // evintString.emit("substract", 3, to_string(2)); - sleep(1); - evoid.off("void"); - evoid.emit("void"); + // sleep(1); + // evoid.off("void"); + // evoid.emit("void"); - /** - * Own class - */ + // /** + // * Own class + // */ - myOwnClass myclass; + // myOwnClass myclass; - timeout t( [&] { - myclass.emit("constructed", 1); - }, 200); + // timeout t( [&] { + // myclass.emit("constructed", 1); + // }, 200); - myclass.on("constructed", [] (int i) { - cout << "Constructed " << i << endl; - }); + // myclass.on("constructed", [] (int i) { + // cout << "Constructed " << i << endl; + // });