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