Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_QUICKTIMER_HH__ 00003 #define __RAPICORN_QUICKTIMER_HH__ 00004 00005 #include <rcore/cpuasm.hh> 00006 #include <rcore/utilities.hh> 00007 00008 namespace Rapicorn { 00009 00010 class QuickTimer { 00011 enum Type { NONE, PROCESS, RDTSC, TIMEOFDAY }; 00012 uint64 usecs_, start_, mark_; 00013 static uint64 volatile timer_pcounter; 00014 static uint64 const granularity = 1700; // rough granularity for expiration checks 00015 static Type timer_type; 00016 static uint64 rdtsc_mask; 00017 static bool toggle_timers (bool); 00018 static void inc_pcounter (); 00019 static void unref_timers (); 00020 static void init_timers (); 00021 static void ref_timers (); 00022 bool time_elapsed (); 00023 RAPICORN_CLASS_NON_COPYABLE (QuickTimer); 00024 public: 00025 explicit QuickTimer (uint64 usecs); 00026 virtual ~QuickTimer (); 00027 void start (); 00028 void start (uint64 usecs); 00029 inline bool expired (); 00030 }; 00031 00032 00033 // === Implementation Details === 00034 inline bool // inlined for performance 00035 QuickTimer::expired() 00036 { 00037 // fast path: QuickTimer::PROCESS and counter hasn't changed 00038 if (RAPICORN_LIKELY (mark_ == timer_pcounter)) 00039 return false; 00040 // fallback to rdtsc polling 00041 if (RAPICORN_HAVE_X86_RDTSC && RAPICORN_LIKELY (timer_type == QuickTimer::RDTSC)) 00042 { 00043 const uint64 rnow = RAPICORN_X86_RDTSC(); 00044 // check: ABS (rnow - last) * 1000000 / rdtsc_timer_freq >= granularity 00045 if (RAPICORN_UNLIKELY ((rnow ^ mark_) & rdtsc_mask)) 00046 { 00047 mark_ = rnow; 00048 return RAPICORN_UNLIKELY (time_elapsed()); 00049 } 00050 return false; 00051 } 00052 // fallback to gettimeofday polling 00053 if (RAPICORN_LIKELY (timer_type == QuickTimer::TIMEOFDAY)) 00054 { 00055 const uint64 tnow = timestamp_realtime(); 00056 if (RAPICORN_UNLIKELY (ABS (tnow - mark_) >= granularity)) 00057 { 00058 mark_ = tnow; 00059 return RAPICORN_UNLIKELY (time_elapsed()); 00060 } 00061 return false; 00062 } 00063 // QuickTimer::PROCESS, counter changed 00064 mark_ = timer_pcounter; // update mark 00065 return RAPICORN_UNLIKELY (time_elapsed()); 00066 } 00067 00068 } // Rapicorn 00069 00070 #endif /* __RAPICORN_QUICKTIMER_HH__ */