Explorar o código

Add Metronome

JDierkse %!s(int64=5) %!d(string=hai) anos
pai
achega
e7d247ca42
Modificáronse 4 ficheiros con 177 adicións e 0 borrados
  1. 21 0
      Timer/Metronome.cpp
  2. 74 0
      Timer/MetronomeImpl.cpp
  3. 44 0
      Timer/MetronomeImpl.h
  4. 38 0
      include/Metronome.h

+ 21 - 0
Timer/Metronome.cpp

@@ -0,0 +1,21 @@
+#include "Metronome.h"
+#include "MetronomeImpl.h"
+
+
+namespace Timer {
+
+Metronome::Metronome(Quantity::type quantity, int amount) :
+	m_pMetronomeImpl(new MetronomeImpl(quantity, amount))
+{
+}
+
+Metronome::~Metronome()
+{
+}
+
+size_t Metronome::Connect(std::function<void()> function)
+{
+	return m_pMetronomeImpl->Connect(function);
+}
+
+} // namespace Timer

+ 74 - 0
Timer/MetronomeImpl.cpp

@@ -0,0 +1,74 @@
+#include "MetronomeImpl.h"
+#include "Trigger.h"
+
+
+namespace Timer {
+
+MetronomeImpl::MetronomeImpl(Metronome::Quantity::type quantity, int amount) :
+	m_work(m_ioService),
+	m_timer(m_ioService),
+	m_quantity(quantity),
+	m_amount(amount)
+{
+	m_thread = std::thread([&] { m_ioService.run(); });
+
+#ifdef __linux__
+	pthread_setname_np(m_thread.native_handle(), "Metronome");
+#endif
+
+	SetTimer();
+}
+
+MetronomeImpl::~MetronomeImpl()
+{
+	m_ioService.stop();
+	m_thread.join();
+}
+
+size_t MetronomeImpl::Connect(std::function<void()> function)
+{
+	return m_signal.connect(function);
+}
+
+void MetronomeImpl::SetTimer()
+{
+	m_timer.expires_at(GetTimePoint());
+	CheckDeadline(asio::error_code());
+}
+
+asio::system_timer::time_point MetronomeImpl::GetTimePoint()
+{
+	switch (m_quantity)
+	{
+		case Metronome::Quantity::Hours:
+			return Trigger::HoursMultitude(m_amount);
+		case Metronome::Quantity::Minutes:
+			return Trigger::MinutesMultitude(m_amount);
+		case Metronome::Quantity::Seconds:
+			return Trigger::SecondsMultitude(m_amount);
+		default:
+			return asio::system_timer::time_point();
+	}
+}
+
+void MetronomeImpl::Trigger()
+{
+	m_signal.emit();
+	SetTimer();
+}
+
+void MetronomeImpl::CheckDeadline(const asio::error_code& ec)
+{
+	if (ec != asio::error::operation_aborted)
+	{
+		if (m_timer.expires_at() <= std::chrono::system_clock::now())
+		{
+			Trigger();
+			SetTimer();
+		}
+
+		m_timer.async_wait(std::bind(&MetronomeImpl::CheckDeadline, this, std::placeholders::_1));
+	}
+}
+
+} // namespace Timer

+ 44 - 0
Timer/MetronomeImpl.h

@@ -0,0 +1,44 @@
+#ifndef TIMER_METRONOMEIMPL_H
+#define TIMER_METRONOMEIMPL_H
+
+#include "Metronome.h"
+#include <SimpleSignal.h>
+#include <asio.hpp>
+#include <functional>
+
+
+namespace Timer {
+
+class MetronomeImpl
+{
+public:
+	MetronomeImpl(Metronome::Quantity::type quantity, int amount);
+	~MetronomeImpl();
+
+	size_t Connect(std::function<void()> function);
+
+private:
+	typedef Simple::Signal<void()> Signal;
+
+private:
+	void SetTimer();
+	asio::system_timer::time_point GetTimePoint();
+	void Trigger();
+	void CheckDeadline(const asio::error_code& ec);
+
+private:
+	std::thread m_thread;
+	asio::io_service m_ioService;
+	asio::io_service::work m_work;
+
+	asio::system_timer m_timer;
+
+	Metronome::Quantity::type m_quantity;
+	int m_amount;
+
+	Signal m_signal;
+};
+
+} // namespace Timer
+
+#endif // TIMER_METRONOMEIMPL_H

+ 38 - 0
include/Metronome.h

@@ -0,0 +1,38 @@
+#ifndef METRONOME_H
+#define METRONOME_H
+
+#include <memory>
+#include <functional>
+
+
+namespace Timer {
+
+class MetronomeImpl;
+
+class Metronome
+{
+public:
+	class Quantity
+	{
+	public:
+		enum type
+		{
+			Hours,
+			Minutes,
+			Seconds
+		};
+	};
+
+public:
+	Metronome(Quantity::type quantity, int amount);
+	~Metronome();
+
+	size_t Connect(std::function<void()> function);
+
+private:
+	std::unique_ptr<MetronomeImpl> m_pMetronomeImpl;
+};
+
+} // namespace Timer
+
+#endif // METRONOME_H