view modules/timer/timer.hpp @ 531:25e6380d0849

Timer: threaded timer import
author David Demelier <markand@malikania.fr>
date Thu, 02 Jun 2016 16:56:30 +0200
parents 409cf1aa4af9
children f7af45aeb197
line wrap: on
line source

/*
 * timer.hpp -- threaded timers
 *
 * Copyright (c) 2016 David Demelier <markand@malikania.fr>
 *
 * 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.
 */

#ifndef TIMER_HPP
#define TIMER_HPP

/**
 * \file timer.hpp
 * \brief Threaded timers.
 */

#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <functional>
#include <mutex>
#include <thread>

/**
 * \brief Threaded timer.
 */
class Timer {
public:
	/**
	 * \brief Type of timer.
	 */
	enum Type {
		/// Periodic timer.
		Repeat,
		/// Oneshot timer.
		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:
	/**
	 * Constructor.
	 *
	 * \param type the type of timer
	 * \param delay the delay in milliseconds
	 */
	inline Timer(Type type, std::uint32_t delay) noexcept
		: m_type(type)
		, m_delay(delay)
	{
	}

	/**
	 * Stop the timer.
	 */
	inline ~Timer()
	{
		stop();
	}

	/**
	 * Get the current handler.
	 *
	 * \return the handler
	 */
	inline const std::function<void ()> &handler() const noexcept
	{
		return m_handler;
	}

	/**
	 * Overloaded function.
	 *
	 * \return the handler
	 */
	inline std::function<void ()> &handler() noexcept
	{
		return m_handler;
	}

	/**
	 * Set the handler.
	 *
	 * \pre !isActive()
	 * \param handler the handler
	 */
	inline void setHandler(std::function<void ()> handler)
	{
		assert(!m_thread.joinable());

		m_handler = std::move(handler);
	}

	/**
	 * Tells if a pending thread is still active even if the execution has finished.
	 *
	 * \return true if active
	 */
	inline bool isActive() const noexcept
	{
		return m_thread.joinable();
	}

	/**
	 * Start the timer.
	 *
	 * \pre the timer must not be running
	 */
	void start();

	/**
	 * Stop the timer.
	 *
	 * Can be safely called multiple times.
	 */
	void stop();
};

#endif // !TIMER_HPP