Ver código fonte

Initial commit

JDierkse 5 anos atrás
commit
daf493b6b4
10 arquivos alterados com 231 adições e 0 exclusões
  1. 7 0
      .gitignore
  2. 3 0
      .gitmodules
  3. 1 0
      Makefile
  4. 6 0
      Makefile.conf
  5. 13 0
      Makefile.target
  6. 1 0
      Makefiles
  7. 1 0
      Timer/Makefile
  8. 57 0
      Timer/Timer.cpp
  9. 108 0
      include/Timer.h
  10. 34 0
      include/TimerHelpers.h

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+*.o.*
+*.d.*
+*.a.*
+.*.swp
+.AppleDouble
+lib
+Libraries

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "Makefiles"]
+	path = Makefiles
+	url = https://gogs.dierkse.nl/JDierkse/Makefiles

+ 1 - 0
Makefile

@@ -0,0 +1 @@
+Makefiles/Makefile

+ 6 - 0
Makefile.conf

@@ -0,0 +1,6 @@
+#
+# Makefile.conf
+#
+
+CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/include -I$(ROOTPATH)/Libraries/Utilities/include
+DEBUGDIR := .debug

+ 13 - 0
Makefile.target

@@ -0,0 +1,13 @@
+#
+# Makefile.target
+#
+
+Timer.a.$(ARCH) : $(OBJECTS)
+	$(call build_target_library_arch,$@,$^)
+
+Timer.a:
+	$(call build_target,$@)
+
+.DEFAULT_GOAL := Timer.a
+
+TARGETS += Timer.a

+ 1 - 0
Makefiles

@@ -0,0 +1 @@
+Subproject commit 61894c4588eb2b85e342a6f923eeb7ac97c3fe64

+ 1 - 0
Timer/Makefile

@@ -0,0 +1 @@
+../Makefile

+ 57 - 0
Timer/Timer.cpp

@@ -0,0 +1,57 @@
+#include "Timer.h"
+#include "Random.h"
+#include <chrono>
+
+
+namespace Timer {
+
+Timer::Timer() :
+	m_run(false),
+	m_aborted(false),
+	m_identifier(Random::CreateRandomString(10))
+{
+}
+
+Timer::~Timer()
+{
+	Abort();
+	Wait();
+}
+
+bool Timer::operator==(const Timer& other) const
+{
+	return m_identifier == other.Identifier();
+}
+
+std::string Timer::Identifier() const
+{
+	return m_identifier;
+}
+
+void Timer::Stop()
+{
+	m_run.store(false, std::memory_order_release);
+}
+
+void Timer::Abort()
+{
+	m_run.store(false, std::memory_order_release);
+	{
+		std::unique_lock<std::mutex> lock(m_mutex);
+		m_aborted = true;
+	}
+	m_conditionVariable.notify_all();
+}
+
+bool Timer::IsRunning() const noexcept
+{
+	return (m_run.load(std::memory_order_acquire) && m_thread.joinable());
+}
+
+void Timer::Wait()
+{
+	if (m_thread.joinable())
+		m_thread.join();
+}
+
+} // namespace Timer

+ 108 - 0
include/Timer.h

@@ -0,0 +1,108 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "TimerHelpers.h"
+#include <atomic>
+#include <condition_variable>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <thread>
+
+
+namespace Timer {
+
+class Timer
+{
+public:
+	Timer();
+	~Timer();
+
+	Timer(const Timer&) = delete;
+	Timer& operator= (const Timer&) = delete;
+
+	bool operator==(const Timer& other) const;
+
+public:
+	std::string Identifier() const;
+
+	template <typename ...FunctionArguments, typename ...Arguments>
+	void StartSingle(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
+	{
+		Start(TimerType::Single, milliSeconds, function, std::forward<Arguments>(arguments)...);
+	}
+
+	template <typename ...FunctionArguments, typename ...Arguments>
+	void StartContinuous(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
+	{
+		Start(TimerType::Continuous, milliSeconds, function, std::forward<Arguments>(arguments)...);
+	}
+
+	void Stop();
+	void Abort();
+	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 milliSeconds, 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, type, milliSeconds, function, &arguments...]()
+			{
+				auto argumentsCopy = std::make_tuple(std::forward<Arguments>(arguments)...);
+				m_run.store(true, std::memory_order_release);
+				m_aborted = false;
+
+				while (m_run.load(std::memory_order_acquire))
+				{
+					std::unique_lock<std::mutex> lock(m_mutex);
+					if (!m_conditionVariable.wait_for(lock, std::chrono::milliseconds(milliSeconds), [&]{return m_aborted;}))
+					{
+						Helpers::execute(function, argumentsCopy);
+						if (type == TimerType::Single)
+							m_run.store(false, std::memory_order_release);
+					}
+				}
+			});
+
+#ifdef __linux__
+		pthread_setname_np(m_thread.native_handle(), "Timer");
+#endif
+
+		while (!IsRunning())
+		{
+		}
+	}
+
+private:
+	std::atomic<bool> m_run;
+	bool m_aborted;
+	std::mutex m_mutex;
+	std::condition_variable m_conditionVariable;
+	std::string m_identifier;
+	std::thread m_thread;
+};
+
+typedef std::unique_ptr<Timer> TimerPointer;
+
+} // namespace Timer
+
+#endif // TIMER_H

+ 34 - 0
include/TimerHelpers.h

@@ -0,0 +1,34 @@
+#ifndef TIMERHELPERS_H
+#define TIMERHELPERS_H
+
+#include <functional>
+
+
+namespace Timer {
+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 Timer
+
+#endif // TIMERHELPERS_H