Much more precise timer functions
This commit is contained in:
		
							parent
							
								
									105c15b06b
								
							
						
					
					
						commit
						4d79b1459a
					
				| @ -38,9 +38,10 @@ namespace { | ||||
| class timer_core { | ||||
|     public: | ||||
|     mutex hangon; | ||||
|     condition_variable cv; | ||||
|     function<void()> 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<void()> _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<mutex> hang(hangon); | ||||
|         // lock_guard<mutex> 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<tcores.size(); i++) { | ||||
|             vector<shared_ptr<timer_core>>::iterator next_tc; | ||||
|             shared_ptr<timer_core> next_ptr; | ||||
| 
 | ||||
|                 if (tcores[i]->stop) { | ||||
|                     remove(i); | ||||
|                     i--; | ||||
|             { | ||||
|             unique_lock<mutex> te_l(te_m); | ||||
|             te_cv.wait(te_l, [this]{ return !tcores.empty(); }); | ||||
|             // calc_next();
 | ||||
| 
 | ||||
|             next_tc = min_element( tcores.begin(), tcores.end(), | ||||
|                 [](shared_ptr<timer_core> a, shared_ptr<timer_core> 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<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); | ||||
|                 } | ||||
|             } | ||||
|             this_thread::sleep_for(chrono::microseconds(sampling)); | ||||
| 
 | ||||
|         }  | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * The method checks whether the time event has expired | ||||
|     */ | ||||
|     bool expired(shared_ptr<timer_core> 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<shared_ptr<timer_core>>::iterator it) { | ||||
|         lock_guard<mutex> 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.size(); i++) { | ||||
|             if (sampling > 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<timer_core> tcore) { | ||||
|         lock_guard<mutex> lock(te_m); | ||||
|         tcores.push_back(tcore); | ||||
|         update_sampling(); | ||||
|         te_cv.notify_one(); | ||||
|     }; | ||||
| 
 | ||||
|     /**
 | ||||
|  | ||||
							
								
								
									
										121
									
								
								test/test.cpp
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								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<int, int> ev2int; | ||||
|     event<int, string> evintString; | ||||
|     event<> evoid; | ||||
|     // event<int, int> ev2int;
 | ||||
|     // event<int, string> 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;
 | ||||
|     // });
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user