mirror of https://github.com/JAJames/jessilib.git
Jessica James
7 years ago
6 changed files with 314 additions and 246 deletions
@ -0,0 +1,93 @@ |
|||
/**
|
|||
* Copyright (C) 2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include "impl/timer_manager.hpp" |
|||
|
|||
namespace jessilib { |
|||
namespace impl { |
|||
|
|||
/** timer_manager */ |
|||
|
|||
timer_manager& timer_manager::instance() { |
|||
static timer_manager s_manager; |
|||
return s_manager; |
|||
} |
|||
|
|||
timer_manager::~timer_manager() { |
|||
m_thread_active = false; |
|||
m_cvar.notify_one(); |
|||
m_thread.join(); |
|||
} |
|||
|
|||
void timer_manager::loop() { |
|||
// loop
|
|||
while (m_thread_active) { |
|||
std::unique_lock<std::mutex> lock(m_mutex); |
|||
auto itr{m_active_timers.begin()}; |
|||
if (itr != m_active_timers.end()) { |
|||
// Wait until the next timer is ready to fire
|
|||
if (m_cvar.wait_until(lock, (*itr)->next()) == std::cv_status::timeout && itr != m_active_timers.end()) { |
|||
// Set active
|
|||
timer* target = *itr; |
|||
m_current_timer = target; |
|||
bool detached = is_detached(*target); |
|||
|
|||
// Execute timer
|
|||
target->m_callback(*target); |
|||
|
|||
// Check if timer still exists
|
|||
itr = m_active_timers.begin(); |
|||
if (itr != m_active_timers.end() && *itr == target) { |
|||
// Timer still exists; extract
|
|||
m_active_timers.erase(itr); |
|||
|
|||
// reset timings
|
|||
target->m_next = target->calc_next(); |
|||
|
|||
// push
|
|||
m_active_timers.insert(target); |
|||
} |
|||
else if (detached) { |
|||
// Timer has been canceled; remove it from the detached timers list
|
|||
std::lock_guard<std::mutex> lock(m_detached_timers_mutex); |
|||
m_detached_timers.erase(target->m_self); |
|||
} |
|||
|
|||
// Reset active
|
|||
m_current_timer = nullptr; |
|||
} |
|||
// else // m_active_timers changed; itr may be invalid; itr may not be the next timer
|
|||
} |
|||
else { |
|||
// Wait until a timer is added
|
|||
m_cvar.wait(lock); |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool timer_manager::is_current(timer& in_timer) { |
|||
return m_current_timer == &in_timer && m_thread.get_id() == std::this_thread::get_id(); |
|||
} |
|||
|
|||
bool timer_manager::is_detached(timer& in_timer) { |
|||
std::lock_guard<std::mutex> lock(m_detached_timers_mutex); |
|||
return in_timer.m_self != m_detached_timers.end(); |
|||
} |
|||
|
|||
} // namespace impl
|
|||
} // namespace jessilib
|
@ -0,0 +1,70 @@ |
|||
/**
|
|||
* Copyright (C) 2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <list> |
|||
#include <set> |
|||
#include <mutex> |
|||
#include <condition_variable> |
|||
#include <atomic> |
|||
#include <thread> |
|||
#include "../timer.hpp" |
|||
|
|||
namespace jessilib { |
|||
namespace impl { |
|||
|
|||
/** timer::manager */ |
|||
|
|||
class timer_manager { |
|||
// Singleton accessor
|
|||
static timer_manager& instance(); |
|||
|
|||
// Destructor
|
|||
~timer_manager(); |
|||
|
|||
struct timer_sort { |
|||
bool operator()(const timer* lhs, const timer* rhs) const { |
|||
return lhs->next() < rhs->next(); |
|||
} |
|||
}; |
|||
|
|||
// Loop
|
|||
void loop(); |
|||
|
|||
// helpers
|
|||
bool is_current(timer& in_timer); |
|||
bool is_detached(timer& in_timer); |
|||
|
|||
// Members
|
|||
std::list<timer> m_detached_timers; |
|||
std::multiset<timer*, timer_sort> m_active_timers; |
|||
std::mutex m_mutex, m_detached_timers_mutex; |
|||
std::condition_variable m_cvar; |
|||
std::atomic<timer*> m_current_timer{nullptr}; |
|||
std::atomic<bool> m_thread_active{true}; |
|||
std::thread m_thread{[this]() { |
|||
loop(); |
|||
}}; |
|||
|
|||
// Friends
|
|||
friend timer; |
|||
}; // class timer_manager
|
|||
|
|||
} // namespace impl
|
|||
} // namespace jessilib
|
Loading…
Reference in new issue