Mercurial > code
changeset 515:409cf1aa4af9
Timer: add experimental threaded timers
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 01 Jun 2016 15:41:22 +0200 |
parents | d89a5e9e5fa7 |
children | cc50a80dc163 |
files | modules/timer/timer.cpp modules/timer/timer.hpp |
diffstat | 2 files changed, 150 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/timer/timer.cpp Wed Jun 01 15:41:22 2016 +0200 @@ -0,0 +1,85 @@ +#include <cassert> + +#include "timer.hpp" + +void Timer::call() +{ + if (m_alive && m_handler) + m_handler(); +} + +void Timer::wait() +{ + std::unique_lock<std::mutex> lock(m_mutex); + + m_condition.wait_for(lock, std::chrono::milliseconds(m_delay), [&] () { + return static_cast<bool>(!m_alive); + }); +} + +void Timer::runOne() +{ + wait(); + call(); +} + +void Timer::runForever() +{ + while (m_alive) { + wait(); + call(); + } +} + +void Timer::start() +{ + assert(!m_thread.joinable()); + + m_alive = true; + + if (m_type == Single) + m_thread = std::thread(std::bind(&Timer::runOne, this)); + else + m_thread = std::thread(std::bind(&Timer::runForever, this)); +} + +void Timer::stop() +{ + if (m_thread.joinable()) { + m_alive = false; + m_condition.notify_one(); + m_thread.join(); + } +} + + + + + + + + +#include <iostream> + +int main() +{ + Timer timer(Timer::Repeat, 500); + + timer.setHandler([] () { std::puts("tu me chatouilles"); }); + auto f = std::move(timer.handler()); + timer.setHandler([&] () { + std::puts("preums"); + f(); + }); + timer.start(); + + std::this_thread::sleep_for(std::chrono::seconds(2)); + std::puts("Je coupe le son..."); + timer.stop(); + std::this_thread::sleep_for(std::chrono::seconds(5)); + std::puts("Je remets le son..."); + timer.start(); + std::this_thread::sleep_for(std::chrono::seconds(2)); + + return 0; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/timer/timer.hpp Wed Jun 01 15:41:22 2016 +0200 @@ -0,0 +1,65 @@ +#ifndef TIMER_HPP +#define TIMER_HPP + +#include <atomic> +#include <condition_variable> +#include <chrono> +#include <cstdint> +#include <functional> +#include <mutex> +#include <thread> + +class Timer { +public: + enum Type { + Repeat, + Single + }; + +private: + Type m_type; + std::atomic<bool> m_alive{true}; + std::thread m_thread; + std::mutex m_mutex; + std::condition_variable m_condition; + std::function<void ()> m_handler; + std::uint32_t m_delay; + + void call(); + void wait(); + void runOne(); + void runForever(); + +public: + inline Timer(Type type, std::uint32_t delay) noexcept + : m_type(type) + , m_delay(delay) + { + } + + inline ~Timer() + { + stop(); + } + + inline const std::function<void ()> &handler() const noexcept + { + return m_handler; + } + + inline std::function<void ()> &handler() noexcept + { + return m_handler; + } + + inline void setHandler(std::function<void ()> handler) + { + m_handler = std::move(handler); + } + + void start(); + + void stop(); +}; + +#endif // !TIMER_HPP \ No newline at end of file