#pragma once #include "AftrConfig.h" #ifdef AFTR_CONFIG_USE_FMT_LIB #include //needed to compile on a Mac #include #include #include #include namespace Aftr { //std::string to_string( AftrTimer::duration_type const& dur ); //See AftrTimer_test.cpp for example usages. This is a fun little timer that is lightweight and uses RAII to report results by default. class AftrTimer { public: //Aliases for the type of time/clock used as well as for the declaration of the call back type using clock_type = std::chrono::steady_clock::time_point::clock; using duration_type = clock_type::duration; using call_back_func_type = std::function; //The "natural" unit of time the AftrTimer uses is a second along with its fractional part stored //as a double. Specifically, this type is a std::chrono::duration that internally stores a //double denoting the time in seconds, including fractions of a second, since this timer was created. using fractional_second_type = std::chrono::duration>; //1:1 ratio implies seconds, double is storage //AftrTimer() = delete; //force default constructor to use default prefix and suffix ///Let's user specify a prefix the is inserted before the timing output. Helpful for a label, for example. AftrTimer( std::string const& prefix_before_timer_output = "", std::string const& suffix = "sec\n"); AftrTimer( call_back_func_type cb, std::string const& prefix_before_timer_output = "", std::string const& suffix = "sec\n" ); AftrTimer( const AftrTimer& toCopy ) = default; AftrTimer( AftrTimer&& toMove) noexcept; AftrTimer& operator=( const AftrTimer& toCopyAssign ) = default; AftrTimer& operator=( AftrTimer&& toMoveAssign ) noexcept; ///Returns the seconds + fractional seconds since this timer was created. So 12.34567 is 12 seconds and 0.34567 seconds fractional_second_type get_elapsed_as_seconds() const noexcept; ///Returns the current duration since this timer's construction clock_type::duration get_elapsed_as_duration() const noexcept; static fractional_second_type get_elapsed_duration_as_seconds( const duration_type& dur ) noexcept; ///Stops the timer, it will *not* invoke the callback or print timing info on destruction but the elapsed ///duration is available via get_elapsed_as_...() methods. ///Calling stop_quietly() more than once has no visible effect. ///After this method returns, the timer is halted -- calls to get_elapsed_...() will ///continue to return the time duration between creation and the point when stop_quietly() was called. ///The timer can no longer be started or used to make a new measurement after calling stop_quietly(). ///Calling stop_quietly() more than once has no visible effect. void stop_quietly() noexcept; ///If not already stopped or aborted, this method will stop the timer and invoke the callback ///or prints timing info. ///After this method returns, the timer is halted -- calls to get_elapsed_...() will ///continue to return the time duration between creation and the point when stop() was called. ///The timer can no longer be started or used to make a new measurement after calling stop(). ///Calling stop() more than once has no visible effect. void stop() noexcept; ///Either prints the time HH:MM:SS.ssss to standard out or invokes the callback passing ///the corresponding duration, if the callback was set during construction ~AftrTimer(); static std::string to_string( const AftrTimer& t ); static std::string to_string( const duration_type& duration, const std::string& prefix = "", const std::string& suffix = "sec" ); static std::string to_string( const fractional_second_type& seconds, const std::string& prefix = "", const std::string& suffix = "sec" ); static void print( const AftrTimer& t ) noexcept; static void print( const fractional_second_type& seconds, const std::string& prefix = "", const std::string& suffix = "sec" ) noexcept; static void print( const duration_type& duration, const std::string& prefix = "", const std::string& suffix = "sec" ) noexcept; call_back_func_type call_back; ///< If set, called by the destructor instead of printing the duration to std out std::string prefix; std::string suffix; clock_type::time_point start_time; ///< Time at which the constructor's last initializer was set private: bool halted{ false }; void shutdown( duration_type&& dur ); std::optional completed_measured_duration; }; //A wrapper around an AftrTimer that invokes the specified callback exactly once *after* countdown_time has elapsed. class AftrCountdownTimer { public: //Returns true if the countdown has expired; false, otherwise. Calling countdown on an expired timer //Count down timer -- This constructor will trigger the callback after expiration_time has elapsed. //Since this is single threaded, the user must query periodically to see if the timer is expired. For example, //say the user desired the callback to be called in 1.5 seconds. The user would then invoke AftrTimer::countdown() //each frame (i.e., many times per second). At the frame where >= 1.5 seconds has elapsed, countdown() would invoke //the callback automatically. If the callback resets the timer, the timer will countdown again until it is destroyed. //Otherwise, the countdown is complete and the timer is in the same state as calling stop_quietly. Further //calls to countdown() do nothing. AftrCountdownTimer( AftrTimer::duration_type countdown_time, AftrTimer::call_back_func_type expiration_func = nullptr ); //Upon invocation, this method resets the timer to the original countdown time. If the timer is either counting //down OR expired, this method will do the same thing and restart the clock returning true from coundown() when //the time has elapsed. void restartCountdown(); //Returns true exactly once upon the first poll where the elapsed time is >= the countdown_time specified in the //c'tor. bool countdown(); private: std::optional timer; AftrTimer::call_back_func_type expire_func; AftrTimer::duration_type countdown_time; }; std::string to_string( AftrTimer::duration_type const& dur, const std::string& prefix = "", const std::string& suffix = "sec" ); }//namespace Aftr #endif