Fix Timer Variadic Template Implementation

This commit is contained in:
2019-02-09 13:31:22 +01:00
parent b623ba5003
commit fcd4b337c5
5 changed files with 114 additions and 16 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ Device::~Device()
void Device::Start() void Device::Start()
{ {
m_timer.Start(10000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this))); m_timer.StartContinuous(10000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this)));
} }
void Device::Stop() void Device::Stop()
+1 -1
View File
@@ -27,7 +27,7 @@ Device::~Device()
void Device::Start() void Device::Start()
{ {
m_timer.Start(5000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this))); m_timer.StartContinuous(5000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this)));
} }
void Device::Stop() void Device::Stop()
+36
View File
@@ -0,0 +1,36 @@
#ifndef UTIL_HELPERS_H
#define UTIL_HELPERS_H
#include <functional>
namespace PresenceDetection {
namespace Util {
namespace Helpers {
template <int... Is>
struct index {};
template <int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
template <int... Is>
struct gen_seq<0, Is...> : index<Is...> {};
template <typename ...FunctionArguments, typename ...Arguments, int... Is>
void execute(std::function<void(FunctionArguments...)> const & function, std::tuple<Arguments...>& tuple, index<Is...>)
{
function(std::get<Is>(tuple)...);
}
template <typename ...FunctionArguments, typename ...Arguments>
void execute(std::function<void(FunctionArguments...)> const & function, std::tuple<Arguments...>& tuple)
{
execute(function, tuple, gen_seq<sizeof...(Arguments)>{});
}
} // namespace Helpers
} // namespace Util
} // namespace PresenceDetection
#endif // UTIL_HELPERS_H
+20
View File
@@ -17,11 +17,31 @@ Timer::~Timer()
Wait(); Wait();
} }
Timer::Timer(Timer&& other) :
m_run(static_cast<bool>(other.m_run)),
m_identifier(other.m_identifier),
m_thread(std::move(other.m_thread))
{
}
Timer& Timer::operator=(Timer&& other)
{
m_run = static_cast<bool>(other.m_run);
m_identifier = std::move(other.m_identifier);
m_thread = std::move(other.m_thread);
return *this;
}
bool Timer::operator==(const Timer& other) const bool Timer::operator==(const Timer& other) const
{ {
return m_identifier == other.Identifier(); return m_identifier == other.Identifier();
} }
bool Timer::operator==(const std::string& identifier) const
{
return m_identifier == identifier;
}
std::string Timer::Identifier() const std::string Timer::Identifier() const
{ {
return m_identifier; return m_identifier;
+56 -14
View File
@@ -1,11 +1,10 @@
#ifndef UTIL_TIMER_H #ifndef UTIL_TIMER_H
#define UTIL_TIMER_H #define UTIL_TIMER_H
#include <iostream>
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <thread> #include <thread>
#include "Helpers.h"
namespace PresenceDetection { namespace PresenceDetection {
@@ -17,32 +16,75 @@ public:
Timer(); Timer();
~Timer(); ~Timer();
Timer(const Timer&) = delete;
Timer& operator= (const Timer&) = delete;
Timer(Timer&& other);
Timer& operator= (Timer&& other);
bool operator==(const Timer& other) const; bool operator==(const Timer& other) const;
bool operator==(const std::string& identifier) const;
public: public:
std::string Identifier() const; std::string Identifier() const;
template <typename ...FunctionArguments, typename ...Arguments> template <typename ...FunctionArguments, typename ...Arguments>
void Start(int interval, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments) void StartSingle(int interval, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
{ {
if (m_run.load(std::memory_order_acquire)) Start(TimerType::Single, interval, function, std::forward<Arguments>(arguments)...);
Stop(); }
m_run.store(true, std::memory_order_release); template <typename ...FunctionArguments, typename ...Arguments>
m_thread = std::thread([this, interval, function, &arguments...]() void StartContinuous(int interval, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
{ {
while (m_run.load(std::memory_order_acquire)) Start(TimerType::Continuous, interval, function, std::forward<Arguments>(arguments)...);
{
function(std::forward<Arguments>(arguments)...);
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
});
} }
void Stop(); void Stop();
bool IsRunning() const noexcept; bool IsRunning() const noexcept;
void Wait(); void Wait();
private:
class TimerType
{
public:
enum type
{
Unknown,
Single,
Continuous
};
};
private:
template <typename ...FunctionArguments, typename ...Arguments>
void Start(TimerType::type type, int interval, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
{
if (type == TimerType::Unknown)
return;
if (m_run.load(std::memory_order_acquire))
Stop();
m_thread = std::thread([this, interval, function, &arguments...]()
{
auto argumentsCopy = std::make_tuple(std::forward<Arguments>(arguments)...);
m_run.store(true, std::memory_order_release);
while (m_run.load(std::memory_order_acquire))
{
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
Helpers::execute(function, argumentsCopy);
if (TimerType::Single)
m_run.store(false, std::memory_order_release);
}
});
while (!IsRunning())
{
}
}
private: private:
std::atomic<bool> m_run; std::atomic<bool> m_run;
std::string m_identifier; std::string m_identifier;