Переглянути джерело

Fix Timer Variadic Template Implementation

JDierkse 6 роки тому
батько
коміт
fcd4b337c5
5 змінених файлів з 109 додано та 11 видалено
  1. 1 1
      Bluetooth/Device.cpp
  2. 1 1
      UniFi/Device.cpp
  3. 36 0
      Util/Helpers.h
  4. 20 0
      Util/Timer.cpp
  5. 51 9
      Util/Timer.h

+ 1 - 1
Bluetooth/Device.cpp

@@ -21,7 +21,7 @@ Device::~Device()
 
 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()

+ 1 - 1
UniFi/Device.cpp

@@ -27,7 +27,7 @@ Device::~Device()
 
 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()

+ 36 - 0
Util/Helpers.h

@@ -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 - 0
Util/Timer.cpp

@@ -17,11 +17,31 @@ Timer::~Timer()
 	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
 {
 	return m_identifier == other.Identifier();
 }
 
+bool Timer::operator==(const std::string& identifier) const
+{
+	return m_identifier == identifier;
+}
+
 std::string Timer::Identifier() const
 {
 	return m_identifier;

+ 51 - 9
Util/Timer.h

@@ -1,11 +1,10 @@
 #ifndef UTIL_TIMER_H
 #define UTIL_TIMER_H
 
-#include <iostream>
-
 #include <atomic>
 #include <functional>
 #include <thread>
+#include "Helpers.h"
 
 
 namespace PresenceDetection {
@@ -17,31 +16,74 @@ public:
 	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 std::string& identifier) const;
 
 public:
 	std::string Identifier() const;
 
 	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)
+	{
+		Start(TimerType::Single, interval, function, std::forward<Arguments>(arguments)...);
+	}
+
+	template <typename ...FunctionArguments, typename ...Arguments>
+	void StartContinuous(int interval, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
+	{
+		Start(TimerType::Continuous, interval, function, std::forward<Arguments>(arguments)...);
+	}
+
+	void Stop();
+	bool IsRunning() const noexcept;
+	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_run.store(true, std::memory_order_release);
 		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))
 				{
-					function(std::forward<Arguments>(arguments)...);
 					std::this_thread::sleep_for(std::chrono::milliseconds(interval));
+					Helpers::execute(function, argumentsCopy);
+					if (TimerType::Single)
+						m_run.store(false, std::memory_order_release);
 				}
 			});
-	}
 
-	void Stop();
-	bool IsRunning() const noexcept;
-	void Wait();
+		while (!IsRunning())
+		{
+		}
+	}
 
 private:
 	std::atomic<bool> m_run;