// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_TIMEr_Hh_ #define DLIB_TIMEr_Hh_ #include <memory> #include "../threads.h" #include "../algs.h" #include "../misc_api.h" #include "timer_abstract.h" #include "../uintn.h" #include "../binary_search_tree.h" #include "timer_heavy.h" namespace dlib { struct timer_base : public threaded_object { /*! WHAT THIS OBJECT REPRESENTS This object contains the base members of the timer object. It exists so that we can access them from outside any templated functions. !*/ unsigned long delay; // these are only modified by the global_clock uint64 next_time_to_run; timestamper ts; bool running; bool in_global_clock; }; // ---------------------------------------------------------------------------------------- class timer_global_clock : private threaded_object { /*! This object sets up a timer that triggers the action function for timer objects that are tracked inside this object. INITIAL VALUE - shutdown == false - running == false CONVENTION - if (shutdown) then - thread() should terminate - else (running) then - thread() is running - tm[time] == pointer to a timer_base object !*/ typedef binary_search_tree<uint64,timer_base*,memory_manager<char>::kernel_2b>::kernel_2a_c time_map; public: ~timer_global_clock(); void add ( timer_base* r ); /*! requires - m is locked ensures - starts the thread if it isn't already started - adds r to tm - #r->in_global_clock == true - updates r->next_time_to_run appropriately according to r->delay !*/ void remove ( timer_base* r ); /*! requires - m is locked ensures - if (r is in tm) then - removes r from tm - #r->in_global_clock == false !*/ void adjust_delay ( timer_base* r, unsigned long new_delay ); /*! requires - m is locked ensures - #r->delay == new_delay - if (r->in_global_clock) then - the time to the next event will have been appropriately adjusted !*/ mutex m; friend std::shared_ptr<timer_global_clock> get_global_clock(); private: timer_global_clock(); time_map tm; signaler s; bool shutdown; bool running; timestamper ts; void thread(); /*! ensures - spawns timer tasks as is appropriate !*/ }; std::shared_ptr<timer_global_clock> get_global_clock(); /*! ensures - returns the global instance of the timer_global_clock object !*/ // ---------------------------------------------------------------------------------------- template < typename T > class timer : private timer_base { /*! INITIAL VALUE - running == false - delay == 1000 - ao == a pointer to the action_object() - af == a pointer to the action_function() - in_global_clock == false - next_time_to_run == 0 - gc == get_global_clock() CONVENTION - the mutex used to lock everything is gc->m - running == is_running() - delay == delay_time() - *ao == action_object() - af == action_function() - if (!running) then - in_global_clock == false - else - next_time_to_run == the next time this timer should run according to the timestamper in the global_clock !*/ public: // These typedefs are here for backwards compatibility with previous versions of // dlib. typedef timer_heavy<T> kernel_1a; typedef timer kernel_2a; typedef void (T::*af_type)(); timer( T& ao_, af_type af_ ); virtual ~timer( ); void clear( ); af_type action_function ( ) const; const T& action_object ( ) const; T& action_object ( ); bool is_running ( ) const; unsigned long delay_time ( ) const; void set_delay_time ( unsigned long milliseconds ); void start ( ); void stop ( ); void stop_and_wait ( ); private: void thread ( ); /*! ensures - calls the action function !*/ // data members T& ao; const af_type af; std::shared_ptr<timer_global_clock> gc; // restricted functions timer(const timer&); // copy constructor timer& operator=(const timer&); // assignment operator }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // member function definitions // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template < typename T > timer<T>:: timer( T& ao_, af_type af_ ) : ao(ao_), af(af_), gc(get_global_clock()) { delay = 1000; next_time_to_run = 0; running = false; in_global_clock = false; } // ---------------------------------------------------------------------------------------- template < typename T > timer<T>:: ~timer( ) { clear(); wait(); } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: clear( ) { auto_mutex M(gc->m); running = false; gc->remove(this); delay = 1000; next_time_to_run = 0; } // ---------------------------------------------------------------------------------------- template < typename T > typename timer<T>::af_type timer<T>:: action_function ( ) const { return af; } // ---------------------------------------------------------------------------------------- template < typename T > const T& timer<T>:: action_object ( ) const { return ao; } // ---------------------------------------------------------------------------------------- template < typename T > T& timer<T>:: action_object ( ) { return ao; } // ---------------------------------------------------------------------------------------- template < typename T > bool timer<T>:: is_running ( ) const { auto_mutex M(gc->m); return running; } // ---------------------------------------------------------------------------------------- template < typename T > unsigned long timer<T>:: delay_time ( ) const { auto_mutex M(gc->m); return delay; } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: set_delay_time ( unsigned long milliseconds ) { auto_mutex M(gc->m); gc->adjust_delay(this,milliseconds); } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: start ( ) { auto_mutex M(gc->m); if (!running) { gc->add(this); running = true; } } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: stop ( ) { gc->m.lock(); running = false; gc->remove(this); gc->m.unlock(); } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: thread ( ) { // call the action function (ao.*af)(); auto_mutex M(gc->m); if (running) { gc->remove(this); gc->add(this); } } // ---------------------------------------------------------------------------------------- template < typename T > void timer<T>:: stop_and_wait ( ) { gc->m.lock(); running = false; gc->remove(this); gc->m.unlock(); wait(); } // ---------------------------------------------------------------------------------------- } #ifdef NO_MAKEFILE #include "timer.cpp" #endif #endif // DLIB_TIMEr_Hh_