7 #ifndef __MERCURY_COROUTINE_ENGINE_TIMER__
8 #define __MERCURY_COROUTINE_ENGINE_TIMER__
12 #include <condition_variable>
38 typedef std::chrono::steady_clock::time_point time_point;
39 typedef std::chrono::steady_clock::duration duration;
50 dur = std::chrono::hours(count);
52 case time_unit::minute:
53 dur = std::chrono::minutes(count);
55 case time_unit::second:
56 dur = std::chrono::seconds(count);
58 case time_unit::millisecond:
59 dur = std::chrono::milliseconds(count);
61 case time_unit::microsecond:
62 dur = std::chrono::microseconds(count);
65 dur = std::chrono::milliseconds(0);
76 auto calc = p0 > p1 ? (p0 - p1) : (p1 - p0);
81 dif = (size_t)(std::chrono::duration_cast<std::chrono::hours>(calc).count());
83 case time_unit::minute:
84 dif = (size_t)(std::chrono::duration_cast<std::chrono::minutes>(calc).count());
86 case time_unit::second:
87 dif = (size_t)(std::chrono::duration_cast<std::chrono::seconds>(calc).count());
89 case time_unit::millisecond:
90 dif = (size_t)(std::chrono::duration_cast<std::chrono::milliseconds>(calc).count());
92 case time_unit::microsecond:
93 dif = (size_t)(std::chrono::duration_cast<std::chrono::microseconds>(calc).count());
105 return std::chrono::steady_clock::now();
135 bool operator==(
const timer_id& rhs) {
return valid == rhs.valid; }
144 std::shared_ptr<bool> valid;
151 continue_running_(false),
154 executing_remove_sync_required_(false),
155 waiting_for_timeouts_(false)
167 std::unique_lock<mce::spinlock> lk(mut_);
168 continue_running_ =
true;
170 executing_remove_sync_required_ =
false;
171 waiting_for_timeouts_ =
false;
172 ready_cv_.notify_all();
178 join_cv_.notify_all();
184 std::unique_lock<mce::spinlock> lk(mut_);
185 while(!running_){ ready_cv_.wait(lk); }
191 std::unique_lock<mce::spinlock> lk(mut_);
192 if(continue_running_) { continue_running_ =
false; }
194 while(running_) { join_cv_.wait(lk); }
204 template <
typename THUNK>
207 return create_timer({ timeout, std::forward<THUNK>(timeout_handler) });
218 template <
typename THUNK>
222 return timer(tp, std::forward<THUNK>(timeout_handler));
234 template <
typename THUNK>
241 case time_unit::hour:
244 case time_unit::minute:
247 case time_unit::second:
250 case time_unit::millisecond:
253 case time_unit::microsecond:
261 return timer(timeout, std::forward<THUNK>(timeout_handler));
267 std::lock_guard<mce::spinlock> lk(mut_);
268 return *(
id.valid) || executing_timer_ ==
id;
285 std::unique_lock<mce::spinlock> lk(mut_);
287 if(executing_timer_ ==
id)
292 executing_remove_sync_required_ =
true;
293 remove_sync_cv.wait(lk);
294 }
while(executing_timer_ ==
id);
300 timer_queue::iterator it;
301 for(it = timers_.begin(); it != timers_.end(); ++it)
306 it = timers_.erase(it);
324 std::lock_guard<mce::spinlock> lk(mut_);
331 std::unique_lock<mce::spinlock> lk(mut_);
332 return timers_.size();
339 thunk timeout_handler;
342 bool operator<(
const timer_data& rhs)
348 bool continue_running_;
351 bool executing_remove_sync_required_;
352 bool waiting_for_timeouts_;
356 using timer_queue = std::list<timer_data>;
362 std::condition_variable_any cv_;
363 std::condition_variable_any ready_cv_;
364 std::condition_variable_any join_cv_;
365 std::condition_variable_any remove_sync_cv;
367 timer_id create_timer(timer_data&& td);
372 id.valid = std::make_shared<bool>(
true);
376 inline void check_timers(std::unique_lock<mce::spinlock>& lk)
378 bool resume_required =
false;
379 mce::time_point cur_time;
380 mce::time_point sleep_time;
381 timer_queue::iterator it;
383 while(continue_running_)
389 it = timers_.begin();
391 while(it != timers_.end())
394 if(it->tp <= cur_time)
396 executing_timer_ = it->id;
397 *(executing_timer_.valid) =
false;
401 const thunk t = std::move(it->timeout_handler);
416 executing_timer_.valid.reset();
418 if(executing_remove_sync_required_)
420 executing_remove_sync_required_ =
false;
421 remove_sync_cv.notify_all();
426 if(!continue_running_) {
break; }
432 resume_required =
true;
438 it = timers_.begin();
442 }
while(new_timers_);
447 if(continue_running_)
452 waiting_for_timeouts_ =
true;
453 cv_.wait_until(lk,sleep_time);
454 resume_required =
false;
459 waiting_for_timeouts_ =
true;
478 inline void operator()()
481 else { timeout_handler(); }
484 std::shared_ptr<mce::scheduler>
scheduler;
498 template <
typename Callable,
typename... As>
506 make_thunk(std::forward<Callable>(cb), std::forward<As>(as)...)
517 template <
typename Callable,
typename... As>
524 make_thunk(std::forward<Callable>(cb), std::forward<As>(as)...)
535 template <
typename Callable,
typename... As>
542 make_thunk(std::forward<Callable>(cb), std::forward<As>(as)...)
571 inline void operator()() { *
success =
true; }
579 std::unique_lock<mce::spinlock> lk(*slk);
588 std::shared_ptr<resumer> resumer_;
596 std::unique_lock<mce::spinlock> lk(slk);
602 std::shared_ptr<wakeup::resumer>(
new wakeup::resumer{ &pk, &slk })
617 inline bool sleep(time_unit u,
size_t count)
@ success
channel is closed, operation failed
Definition: base_channel.hpp:26
std::function< void()> thunk
thunk type definition. Also known as a nullary function
Definition: function_utility.hpp:72
bool in_scheduler()
returns true if calling scope is executing inside a running scheduler
Definition: scheduler.hpp:1095
scheduler & this_scheduler()
returns a shared pointer to the scheduler the calling scope is running in
Definition: scheduler.hpp:1106
Definition: timer.hpp:476
object containing information to block and unblock a coroutine (running in a scheduler) or thread
Definition: scheduler.hpp:268
void park(LOCK &lk)
blocking call until unpark, unlocks and relocks given lock as necessary
Definition: scheduler.hpp:283
object responsible for scheduling and executing coroutines
Definition: scheduler.hpp:180
void schedule(A &&a, As &&... as)
schedule allocated coroutine(s)
Definition: scheduler.hpp:714
Core mechanism for atomic synchronization.
Definition: atomic.hpp:20
Definition: timer.hpp:133
Definition: timer.hpp:131
void clear()
remove all pending timers
Definition: timer.hpp:322
size_t count()
Return the number of running timers.
Definition: timer.hpp:329
timer_id timer(const time_unit u, size_t count, THUNK &&timeout_handler)
start timer
Definition: timer.hpp:235
timer_service()
default constructor
Definition: timer.hpp:150
bool running(timer_id id)
return true if timer is running, else false
Definition: timer.hpp:265
timer_id timer(const mce::time_point &timeout, THUNK &&timeout_handler)
start timer
Definition: timer.hpp:205
timer_id timer(const mce::duration &d, THUNK &&timeout_handler)
start timer
Definition: timer.hpp:219
void start()
start timer service on current thread
Definition: timer.hpp:165
bool remove(timer_id id)
remove a running timer
Definition: timer.hpp:281
void shutdown()
inform service to shutdown and join with service
Definition: timer.hpp:189
~timer_service()
Definition: timer.hpp:162
void ready()
blocks until service is running
Definition: timer.hpp:182
mce::time_point current_time()
Return the current time. All mce timer time operations are calculated using this function.
Definition: timer.hpp:103
timer_id timer(time_unit u, size_t count, Callable &&cb, As &&... as)
launch a timer with a Callable to be called on timeout
Definition: timer.hpp:499
bool remove_timer(timer_id id)
remove a running timer, return true if successful, else false
Definition: timer.hpp:547
mce::duration get_duration(mce::time_unit u, size_t count)
Return duration for count units of the given time unit.
Definition: timer.hpp:44
size_t get_time_point_difference(mce::time_unit u, mce::time_point p0, mce::time_point p1)
Return the difference in time units between two time points.
Definition: timer.hpp:72
timer_service::timer_id timer_id
define mce::timer_id
Definition: timer.hpp:468
bool sleep(mce::duration d)
Put coroutine or thread to sleep in a blocking fashion.
Definition: timer.hpp:563
timer_service & default_timer_service()
Access to default mce::timer_service object.
size_t count_timers()
return a count of running timers
Definition: timer.hpp:553