From e7d247ca426a550f036a4e134f9eebaab247dd29 Mon Sep 17 00:00:00 2001 From: JDierkse Date: Wed, 10 Jun 2020 09:28:55 +0200 Subject: [PATCH] Add Metronome --- Timer/Metronome.cpp | 21 ++++++++++++ Timer/MetronomeImpl.cpp | 74 +++++++++++++++++++++++++++++++++++++++++ Timer/MetronomeImpl.h | 44 ++++++++++++++++++++++++ include/Metronome.h | 38 +++++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 Timer/Metronome.cpp create mode 100644 Timer/MetronomeImpl.cpp create mode 100644 Timer/MetronomeImpl.h create mode 100644 include/Metronome.h diff --git a/Timer/Metronome.cpp b/Timer/Metronome.cpp new file mode 100644 index 0000000..00f7b36 --- /dev/null +++ b/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 function) +{ + return m_pMetronomeImpl->Connect(function); +} + +} // namespace Timer diff --git a/Timer/MetronomeImpl.cpp b/Timer/MetronomeImpl.cpp new file mode 100644 index 0000000..a7a07d4 --- /dev/null +++ b/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 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 diff --git a/Timer/MetronomeImpl.h b/Timer/MetronomeImpl.h new file mode 100644 index 0000000..0ff5dc9 --- /dev/null +++ b/Timer/MetronomeImpl.h @@ -0,0 +1,44 @@ +#ifndef TIMER_METRONOMEIMPL_H +#define TIMER_METRONOMEIMPL_H + +#include "Metronome.h" +#include +#include +#include + + +namespace Timer { + +class MetronomeImpl +{ +public: + MetronomeImpl(Metronome::Quantity::type quantity, int amount); + ~MetronomeImpl(); + + size_t Connect(std::function function); + +private: + typedef Simple::Signal 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 diff --git a/include/Metronome.h b/include/Metronome.h new file mode 100644 index 0000000..d53fd5d --- /dev/null +++ b/include/Metronome.h @@ -0,0 +1,38 @@ +#ifndef METRONOME_H +#define METRONOME_H + +#include +#include + + +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 function); + +private: + std::unique_ptr m_pMetronomeImpl; +}; + +} // namespace Timer + +#endif // METRONOME_H