diff --git a/corsika/detail/framework/analytics/ClassTimer.inl b/corsika/detail/framework/analytics/ClassTimer.inl index 813e765a1971a52aed937c50724d926e893a8965..2d288216cbcec0fe11ce6e4a044d07f9554370eb 100644 --- a/corsika/detail/framework/analytics/ClassTimer.inl +++ b/corsika/detail/framework/analytics/ClassTimer.inl @@ -22,59 +22,59 @@ namespace corsika { // Common template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...)> - ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::ClassTimer(TClass& obj) - : ClassTimerImpl<TClass>(obj) {} + TRet (TClass::*TFuncPtr)(TArgs...), typename TTimer> + ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr, TTimer>::ClassTimer(TClass& obj) + : ClassTimerImpl<TClass, TTimer>(obj) {} template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...)> - TRet ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr>::call(TArgs... args) { - this->start_ = ClassTimerImpl<TClass>::TClock::now(); + TRet (TClass::*TFuncPtr)(TArgs...), typename TTimer> + TRet ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr, TTimer>::call(TArgs... args) { + this->start_ = ClassTimerImpl<TClass,TTimer>::clock_type::now(); auto tmp = (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...); - this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass>::TDuration>(ClassTimerImpl<TClass>::TClock::now() - this->start_); + this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass,TTimer>::duration_type>(ClassTimerImpl<TClass,TTimer>::clock_type::now() - this->start_); return tmp; } // Specialisation 1 - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)> - ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::ClassTimer(TClass& obj) - : ClassTimerImpl<TClass>(obj) {} + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...), typename TTimer> + ClassTimer<void (TClass::*)(TArgs...), TFuncPtr, TTimer>::ClassTimer(TClass& obj) + : ClassTimerImpl<TClass,TTimer>(obj) {} - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)> - void ClassTimer<void (TClass::*)(TArgs...), TFuncPtr>::call(TArgs... args) { - this->start_ = ClassTimerImpl<TClass>::TClock::now(); + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...), typename TTimer> + void ClassTimer<void (TClass::*)(TArgs...), TFuncPtr, TTimer>::call(TArgs... args) { + this->start_ = ClassTimerImpl<TClass,TTimer>::clock_type::now(); (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...); - this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass>::TDuration>(ClassTimerImpl<TClass>::TClock::now() - this->start_); + this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass,TTimer>::duration_type>(ClassTimerImpl<TClass,TTimer>::clock_type::now() - this->start_); return; } /// Specialisation 2 template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...) const> - ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::ClassTimer(TClass& obj) - : ClassTimerImpl<TClass>(obj) {} + TRet (TClass::*TFuncPtr)(TArgs...) const, typename TTimer> + ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::ClassTimer(TClass& obj) + : ClassTimerImpl<TClass,TTimer>(obj) {} template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...) const> - TRet ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr>::call(TArgs... args) { - this->start_ = ClassTimerImpl<TClass>::TClock::now(); + TRet (TClass::*TFuncPtr)(TArgs...) const, typename TTimer> + TRet ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::call(TArgs... args) { + this->start_ = ClassTimerImpl<TClass,TTimer>::clock_type::now(); auto tmp = (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...); - this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass>::TDuration>(ClassTimerImpl<TClass>::TClock::now() - this->start_); + this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass,TTimer>::duration_type>(ClassTimerImpl<TClass,TTimer>::clock_type::now() - this->start_); return tmp; } /// Specialisation 3 - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const> - ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::ClassTimer(TClass& obj) - : ClassTimerImpl<TClass>(obj) {} + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const, typename TTimer = Timer<std::chrono::high_resolution_clock, std::chrono::microseconds>> + ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::ClassTimer(TClass& obj) + : ClassTimerImpl<TClass,TTimer>(obj) {} - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const> - void ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr>::call(TArgs... args) { - this->start_ = ClassTimerImpl<TClass>::TClock::now(); + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const, typename TTimer = Timer<std::chrono::high_resolution_clock, std::chrono::microseconds>> + void ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr, TTimer>::call(TArgs... args) { + this->start_ = ClassTimerImpl<TClass,TTimer>::clock_type::now(); (this->obj_.*TFuncPtr)(std::forward<TArgs>(args)...); - this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass>::TDuration>(ClassTimerImpl<TClass>::TClock::now() - this->start_); + this->timeDiff_ = std::chrono::duration_cast<typename ClassTimerImpl<TClass,TTimer>::duration_type>(ClassTimerImpl<TClass,TTimer>::clock_type::now() - this->start_); return; } diff --git a/corsika/detail/framework/analytics/FunctionTimer.inl b/corsika/detail/framework/analytics/FunctionTimer.inl index a40a4a838272d1b153623d93d5f70330c70b0cbd..e00bebc338db81acf099763e01adb7cc3a3d3bf5 100644 --- a/corsika/detail/framework/analytics/FunctionTimer.inl +++ b/corsika/detail/framework/analytics/FunctionTimer.inl @@ -12,23 +12,18 @@ namespace corsika { - template <typename TFunc, typename TClock, typename TDuration> - FunctionTimer<TFunc, TClock, TDuration>::FunctionTimer(TFunc f) + template <typename TFunc, typename TTime> + FunctionTimer<TFunc, TTime>::FunctionTimer(TFunc f) : function_(f) {} - template <typename TFunc, typename TClock, typename TDuration> + template <typename TFunc, typename TTime> template <typename... TArgs> - auto FunctionTimer<TFunc, TClock, TDuration>::operator()(TArgs&&... args) + auto FunctionTimer<TFunc, TTime>::operator()(TArgs&&... args) -> std::invoke_result_t<TFunc, TArgs...> { - start_ = TClock::now(); + this->startTimer(); auto tmp = function_(std::forward<TArgs>(args)...); - timeDiff_ = std::chrono::duration_cast<TDuration>(TClock::now() - start_); + this->stopTimer(); return tmp; } - template <typename TFunc, typename TClock, typename TDuration> - inline TDuration FunctionTimer<TFunc, TClock, TDuration>::getTime() const { - return timeDiff_; - } - } // namespace corsika diff --git a/corsika/framework/analytics/ClassTimer.hpp b/corsika/framework/analytics/ClassTimer.hpp index 59ee8c8a2b612b9c315e7948cf4ba8026995a839..7958f6f81badb96b16e6ca4198ae9eb685b450d5 100644 --- a/corsika/framework/analytics/ClassTimer.hpp +++ b/corsika/framework/analytics/ClassTimer.hpp @@ -17,32 +17,21 @@ #include <chrono> #include <utility> -namespace corsika { +#include <corsika/framework/analytics/Timer.hpp> - template <class TClass> - class ClassTimerImpl { - protected: - /// Default clock used for time measurement - using TClock = std::chrono::high_resolution_clock; +namespace corsika { - /// Internal resolution of the time measurement - using TDuration = std::chrono::microseconds; + template <class TClass, typename TTimer> + class ClassTimerImpl : public TTimer{ + static_assert(is_timer_v<TTimer>, "TTimer is not a timer!"); // Better https://en.cppreference.com/w/cpp/language/constraints but not available in C++17 + protected: /// Reference to the class object on which the function should be called TClass& obj_; - /// Startpoint of time measurement - typename TClock::time_point start_; - - /// Measured runtime of the function - TDuration timeDiff_; - public: ClassTimerImpl(TClass& obj) : obj_(obj){}; - - /// returns the last runtime of the wraped function accessed via call - inline TDuration getTime() const{return timeDiff_;} }; /// Measure the runtime of a single class function @@ -50,7 +39,7 @@ namespace corsika { * @tparam TClassFunc Type of the member function pointer that should be wrapped * @tparam TFunc Actual function of the type defined in TClass */ - template <typename TClassFunc, TClassFunc TFunc> + template <typename TClassFunc, TClassFunc TFunc, typename TTimer = Timer<std::chrono::high_resolution_clock, std::chrono::microseconds>> class ClassTimer; /// Measure the runtime of a single class function @@ -67,8 +56,8 @@ namespace corsika { * TClass::TFuncPtr(TArgs...) */ template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...)> - class ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr> : public ClassTimerImpl<TClass> { + TRet (TClass::*TFuncPtr)(TArgs...), typename TTimer> + class ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr, TTimer> : public ClassTimerImpl<TClass, TTimer> { private: public: ClassTimer(TClass& obj); @@ -85,12 +74,8 @@ namespace corsika { }; /// Specialisation for member functions without return value - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)> - class ClassTimer<void (TClass::*)(TArgs...), TFuncPtr> : public ClassTimerImpl<TClass> { - private: - using TClock = std::chrono::high_resolution_clock; - using TDuration = std::chrono::microseconds; - + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...), typename TTimer> + class ClassTimer<void (TClass::*)(TArgs...), TFuncPtr, TTimer> : public ClassTimerImpl<TClass, TTimer> { public: ClassTimer(TClass& obj); @@ -99,9 +84,9 @@ namespace corsika { /// Specialisation for const member functions template <typename TClass, typename TRet, typename... TArgs, - TRet (TClass::*TFuncPtr)(TArgs...) const> - class ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr> - : public ClassTimerImpl<TClass> { + TRet (TClass::*TFuncPtr)(TArgs...) const, typename TTimer> + class ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr, TTimer> + : public ClassTimerImpl<TClass, TTimer> { public: ClassTimer(TClass& obj); @@ -109,9 +94,9 @@ namespace corsika { }; /// Specialisation for const member functions without return value - template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const> - class ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr> - : public ClassTimerImpl<TClass> { + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const, typename TTimer> + class ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr, TTimer> + : public ClassTimerImpl<TClass, TTimer> { public: ClassTimer(TClass& obj); diff --git a/corsika/framework/analytics/FunctionTimer.hpp b/corsika/framework/analytics/FunctionTimer.hpp index 0d19bdc28a474cdda33bad0e2cfc6b2bc3e7c361..2a3f5d89a11859ce671912f07a1077d2d4297e50 100644 --- a/corsika/framework/analytics/FunctionTimer.hpp +++ b/corsika/framework/analytics/FunctionTimer.hpp @@ -9,6 +9,9 @@ #include <chrono> #include <utility> +#include <type_traits> + +#include <corsika/framework/analytics/Timer.hpp> namespace corsika { @@ -21,10 +24,9 @@ namespace corsika { * @tparam TDuration type of std::duration to measure the elapsed time, default is * microseconds */ - template <typename TFunc, typename TClock = std::chrono::high_resolution_clock, - typename TDuration = std::chrono::microseconds> - class FunctionTimer { - + template <typename TFunc, class TTimer = Timer<std::chrono::high_resolution_clock, std::chrono::microseconds>> + class FunctionTimer : public TTimer{ + static_assert(is_timer_v<TTimer>, "TTimer is not a timer!"); // Better https://en.cppreference.com/w/cpp/language/constraints but not available in C++17 public: /** Constructs the wrapper with the given functionpointer * @param f Function or functor whose runtime should be measured @@ -44,17 +46,8 @@ namespace corsika { template <typename... TArgs> auto operator()(TArgs&&... args) -> std::invoke_result_t<TFunc, TArgs...>; - /** - * Returns the runtime of the last call to the wrapped function - * @return Returns the measured runtime of the wrapped function/functor in the unit - *given by TDuration - **/ - inline TDuration getTime() const; - - private: - typename TClock::time_point start_; - TDuration timeDiff_; + private: TFunc function_; }; diff --git a/corsika/framework/analytics/Timer.hpp b/corsika/framework/analytics/Timer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d3040c98b698b41023e11af548211ad6f67e7808 --- /dev/null +++ b/corsika/framework/analytics/Timer.hpp @@ -0,0 +1,61 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +#include <chrono> +#include <utility> + +#include <type_traits> + +namespace corsika { + + template <typename TClock = std::chrono::high_resolution_clock, + typename TDuration = std::chrono::microseconds> + class Timer { + protected: + /// Default clock used for time measurement + using clock_type = TClock; + + /// Internal resolution of the time measurement + using duration_type = TDuration; + + /// Startpoint of time measurement + typename clock_type::time_point start_; + + /// Measured runtime of the function + duration_type timeDiff_; + + public: + Timer() + : timeDiff_(0){}; + + /// Start the timer + inline void startTimer() { start_ = clock_type::now(); } + + /// Stop the timer + inline void stopTimer() { + timeDiff_ = std::chrono::duration_cast<duration_type>(clock_type::now() - start_); + } + + /** + * Returns the runtime of the last call to the wrapped function + * @return Returns the measured runtime of the wrapped function/functor in the unit + * given by TDuration + **/ + inline duration_type getTime() const { return timeDiff_; } + }; + + std::false_type is_timer_impl(...); + template <typename T, typename U> + std::true_type is_timer_impl(Timer<T, U> const volatile&); + + template <typename T> + inline constexpr bool is_timer_v = std::is_same_v< decltype(is_timer_impl(std::declval<T&>())), std::true_type>; + +} // namespace corsika \ No newline at end of file