commit daf493b6b4585f0de27cc9cdb05638c2c5859f14 Author: JDierkse Date: Wed Feb 12 19:59:41 2020 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a201fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o.* +*.d.* +*.a.* +.*.swp +.AppleDouble +lib +Libraries diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..876e403 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Makefiles"] + path = Makefiles + url = https://gogs.dierkse.nl/JDierkse/Makefiles diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..6aa5187 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +Makefiles/Makefile \ No newline at end of file diff --git a/Makefile.conf b/Makefile.conf new file mode 100644 index 0000000..d196d52 --- /dev/null +++ b/Makefile.conf @@ -0,0 +1,6 @@ +# +# Makefile.conf +# + +CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/include -I$(ROOTPATH)/Libraries/Utilities/include +DEBUGDIR := .debug diff --git a/Makefile.target b/Makefile.target new file mode 100644 index 0000000..d7e8967 --- /dev/null +++ b/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 diff --git a/Makefiles b/Makefiles new file mode 160000 index 0000000..61894c4 --- /dev/null +++ b/Makefiles @@ -0,0 +1 @@ +Subproject commit 61894c4588eb2b85e342a6f923eeb7ac97c3fe64 diff --git a/Timer/Makefile b/Timer/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Timer/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/Timer/Timer.cpp b/Timer/Timer.cpp new file mode 100644 index 0000000..89b7963 --- /dev/null +++ b/Timer/Timer.cpp @@ -0,0 +1,57 @@ +#include "Timer.h" +#include "Random.h" +#include + + +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 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 diff --git a/include/Timer.h b/include/Timer.h new file mode 100644 index 0000000..fca89bd --- /dev/null +++ b/include/Timer.h @@ -0,0 +1,108 @@ +#ifndef TIMER_H +#define TIMER_H + +#include "TimerHelpers.h" +#include +#include +#include +#include +#include +#include + + +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 + void StartSingle(int milliSeconds, std::function const & function, Arguments && ...arguments) + { + Start(TimerType::Single, milliSeconds, function, std::forward(arguments)...); + } + + template + void StartContinuous(int milliSeconds, std::function const & function, Arguments && ...arguments) + { + Start(TimerType::Continuous, milliSeconds, function, std::forward(arguments)...); + } + + void Stop(); + void Abort(); + bool IsRunning() const noexcept; + void Wait(); + +private: + class TimerType + { + public: + enum type + { + Unknown, + Single, + Continuous + }; + }; + +private: + template + void Start(TimerType::type type, int milliSeconds, std::function 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)...); + m_run.store(true, std::memory_order_release); + m_aborted = false; + + while (m_run.load(std::memory_order_acquire)) + { + std::unique_lock 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 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 TimerPointer; + +} // namespace Timer + +#endif // TIMER_H diff --git a/include/TimerHelpers.h b/include/TimerHelpers.h new file mode 100644 index 0000000..6fc3003 --- /dev/null +++ b/include/TimerHelpers.h @@ -0,0 +1,34 @@ +#ifndef TIMERHELPERS_H +#define TIMERHELPERS_H + +#include + + +namespace Timer { +namespace Helpers { + +template +struct index {}; + +template +struct gen_seq : gen_seq {}; + +template +struct gen_seq<0, Is...> : index {}; + +template +void execute(std::function const & function, std::tuple& tuple, index) +{ + function(std::get(tuple)...); +} + +template +void execute(std::function const & function, std::tuple& tuple) +{ + execute(function, tuple, gen_seq{}); +} + +} // namespace Helpers +} // namespace Timer + +#endif // TIMERHELPERS_H