Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

clock.cpp

Go to the documentation of this file.
00001 // PTF - Psychological Test Framework 00002 // http://ptf.sourceforge.net 00003 // 00004 // This program is free software; you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation; either version 2 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Library General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 #include <ptf/environment/clock.hpp> 00019 #include <ptf/core/ptfcore.hpp> 00020 #if _POSIX_VERSION < 199309 00021 #ifndef _POSIX_TIMERS 00022 #include <sys/time.h> 00023 #endif 00024 #endif 00025 #ifdef MAC 00026 #include <mach/mach_time.h> 00027 #include <mach/mach.h> 00028 #include <mach/clock.h> 00029 // global variables 00030 static uint64_t relative_time, startup_time; 00031 static double timebase_ratio; 00032 static mach_port_t clock_port; 00033 #endif 00034 #include <stdexcept> 00035 00036 #ifdef MAC 00040 void initMachTimer(){ 00041 mach_timebase_info_data_t timebase; 00042 memset( &timebase, 0, sizeof( timebase )); 00043 // get base for mach_absolute_time() 00044 mach_timebase_info(&timebase); 00045 timebase_ratio = (double)timebase.numer / (double)timebase.denom * (double)1e-9; 00046 // get mach port for the clock 00047 host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port); 00048 // prepare for GetRelativeTime() 00049 relative_time = startup_time = (uint64_t)(mach_absolute_time() * timebase_ratio); 00050 } 00051 00056 uint64_t getMachTimer(){ 00057 return (uint64_t)((mach_absolute_time() * timebase_ratio) * 1e6); 00058 } 00059 #endif 00060 00064 Clock::Clock() { 00065 timespec tspec1, tspec2; 00066 PtfCore::getSingleton().getMessageLog() << MESSAGE("Checking clock capabilities.\n"); 00067 // Initialize darwin's timer in case of OS is Mac OS X 00068 #ifdef MAC 00069 PtfCore::getSingleton().getMessageLog() 00070 << MESSAGE("Using Mac OS X high resolution timer. Initializing it now.\n"); 00071 initMachTimer(); 00072 #endif 00073 // check for POSIX.4 clocks and timer support 00074 #ifdef _POSIX_TIMERS 00075 PtfCore::getSingleton().getMessageLog() << MESSAGE("POSIX.4 timers and clocks support.\n"); 00076 clock_getres(CLOCK_REALTIME, &tspec1); 00077 #else 00078 PtfCore::getSingleton().getMessageLog() 00079 << WARNING("POSIX.4 timers and clocks not supported. Using low resolution timing.\n"); 00080 #endif 00081 calculateClockResolution(tspec2); 00082 #ifdef _POSIX_TIMERS 00083 PtfCore::getSingleton().getMessageLog() << MESSAGE("System reported this clock resolution: ") 00084 << tspec1 << "\n"; 00085 #endif 00086 PtfCore::getSingleton().getMessageLog() << MESSAGE("PTF has calculated this clock resolution: ") 00087 << tspec2 << "\n"; 00088 } 00089 00093 Clock::~Clock() { 00094 // nothing to do here 00095 } 00096 00102 void Clock::getClock(timespec& tspec) { 00103 #ifdef _POSIX_TIMERS 00104 // use POSIX timer 00105 clock_gettime(CLOCK_REALTIME, &tspec); 00106 #else 00107 #ifdef MAC 00108 // use MACH timer on MacOs 00109 uint64_t current_time = getMachTimer() * 1000; 00110 tspec.tv_nsec = current_time % (uint64_t)1e9; 00111 tspec.tv_sec = (int)(current_time / 1e9); 00112 #else 00113 // use gettimeofday as fallback 00114 int err; 00115 struct timeval tv; 00116 struct timezone tz; 00117 err = gettimeofday(&tv, &tz); 00118 if(0 != err) { 00119 PtfCore::getSingleton().getMessageLog() 00120 << "ERROR: Failed to get time from low resolution timer.\n"; 00121 throw std::runtime_error("Failed to get time from low resolution timer."); 00122 }; 00123 tspec.tv_sec = (long int)tv.tv_sec; 00124 tspec.tv_nsec = (long int)tv.tv_usec * 1000; 00125 #endif 00126 #endif 00127 } 00128 00136 void Clock::calculateClockResolution(timespec& tspec) { 00137 timespec tspec1, tspec2; 00138 getClock(tspec1); 00139 do { 00140 getClock(tspec2); 00141 } while ((tspec1.tv_nsec == tspec2.tv_nsec) && ((tspec1.tv_sec == tspec2.tv_sec))); 00142 if (tspec1.tv_sec == tspec2.tv_sec) { 00143 tspec.tv_nsec = tspec2.tv_nsec - tspec1.tv_nsec; 00144 tspec.tv_sec = 0; 00145 } 00146 else { 00147 tspec.tv_nsec = 1000000000 - tspec1.tv_nsec + tspec2.tv_nsec; 00148 if (tspec.tv_nsec >= 1000000000) { 00149 tspec.tv_nsec -= 1000000000; 00150 tspec.tv_sec = tspec2.tv_sec - tspec1.tv_sec; 00151 } 00152 else { 00153 tspec.tv_sec = tspec2.tv_sec - tspec1.tv_sec - 1; 00154 } 00155 } 00156 }

Generated on Fri Dec 17 14:54:23 2004 for Psychological Test Framework by doxygen 1.3.8