00001 //---------------------------------------------------------------------------- 00002 /** @file SgTime.cpp 00003 See SgTime.h. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "SgSystem.h" 00007 #include "SgTime.h" 00008 00009 #include <cstring> 00010 #include <ctime> 00011 #include <iomanip> 00012 #include <limits> 00013 #include <iostream> 00014 #include <sstream> 00015 #include <errno.h> 00016 #if WIN32 00017 #include <Windows.h> 00018 #else 00019 #include <sys/times.h> 00020 #include <unistd.h> 00021 #endif 00022 #include <boost/date_time/posix_time/posix_time.hpp> 00023 #include "SgException.h" 00024 00025 using namespace std; 00026 using boost::posix_time::microsec_clock; 00027 using boost::posix_time::ptime; 00028 using boost::posix_time::time_duration; 00029 00030 //---------------------------------------------------------------------------- 00031 00032 namespace { 00033 00034 SgTimeMode g_defaultMode = SG_TIME_REAL; 00035 00036 bool g_isInitialized = false; 00037 00038 ptime g_start; 00039 00040 #if ! WIN32 00041 clock_t g_ticksPerSecond; 00042 00043 clock_t g_ticksPerMinute; 00044 #endif 00045 00046 void Init() 00047 { 00048 #if ! WIN32 00049 long ticksPerSecond = sysconf(_SC_CLK_TCK); 00050 if (ticksPerSecond < 0) // Shouldn't happen 00051 throw SgException("Could not get _SC_CLK_TCK."); 00052 g_ticksPerSecond = static_cast<clock_t>(ticksPerSecond); 00053 g_ticksPerMinute = 60 * g_ticksPerSecond; 00054 #endif 00055 g_start = microsec_clock::universal_time(); 00056 g_isInitialized = true; 00057 } 00058 00059 } // namespace 00060 00061 //---------------------------------------------------------------------------- 00062 00063 string SgTime::Format(double time, bool minsAndSecs) 00064 { 00065 ostringstream out; 00066 if (minsAndSecs) 00067 { 00068 int mins = static_cast<int>(time / 60); 00069 int secs = static_cast<int>(time - mins * 60); 00070 out << setw(2) << mins << ':' << setw(2) << setfill('0') 00071 << secs; 00072 } 00073 else 00074 out << setprecision(2) << fixed << time; 00075 return out.str(); 00076 } 00077 00078 double SgTime::Get() 00079 { 00080 return Get(g_defaultMode); 00081 } 00082 00083 double SgTime::Get(SgTimeMode mode) 00084 { 00085 if (! g_isInitialized) 00086 Init(); 00087 switch (mode) 00088 { 00089 case SG_TIME_CPU: 00090 { 00091 #if WIN32 00092 FILETIME creationTime; 00093 FILETIME exitTime; 00094 FILETIME kernelTime; 00095 FILETIME userTime; 00096 HANDLE handle = GetCurrentProcess(); 00097 if (! GetProcessTimes(handle, &creationTime, &exitTime, &kernelTime, &userTime)) 00098 throw SgException("GetProcessTimes() returned an error"); 00099 // Do not cast FILETIME to ULARGE_INTEGER because it can cause alignment 00100 // faults on 64-bit Windows (according to MSDN docs) 00101 ULARGE_INTEGER kernelInteger; 00102 kernelInteger.LowPart = kernelTime.dwLowDateTime; 00103 kernelInteger.HighPart = kernelTime.dwHighDateTime; 00104 ULARGE_INTEGER userInteger; 00105 userInteger.LowPart = userTime.dwLowDateTime; 00106 userInteger.HighPart = userTime.dwHighDateTime; 00107 ULARGE_INTEGER totalTime; 00108 totalTime.QuadPart= kernelInteger.QuadPart + userInteger.QuadPart; 00109 return double(totalTime.QuadPart * 1e-7); 00110 #else 00111 // Implementation using POSIX functions 00112 struct tms buf; 00113 if (times(&buf) == static_cast<clock_t>(-1)) 00114 { 00115 std::cerr << "Time measurement overflow.\n"; 00116 return 0; 00117 } 00118 clock_t clockTicks = 00119 buf.tms_utime + buf.tms_stime 00120 + buf.tms_cutime + buf.tms_cstime; 00121 return double(clockTicks) / double(g_ticksPerSecond); 00122 #endif 00123 } 00124 case SG_TIME_REAL: 00125 { 00126 time_duration diff = microsec_clock::universal_time() - g_start; 00127 return double(diff.total_nanoseconds()) * 1e-9; 00128 } 00129 default: 00130 SG_ASSERT(false); 00131 return 0; 00132 } 00133 } 00134 00135 SgTimeMode SgTime::DefaultMode() 00136 { 00137 return g_defaultMode; 00138 } 00139 00140 void SgTime::SetDefaultMode(SgTimeMode mode) 00141 { 00142 g_defaultMode = mode; 00143 } 00144 00145 string SgTime::TodaysDate() 00146 { 00147 time_t systime = time(0); 00148 struct tm* currtime = localtime(&systime); 00149 const int BUF_SIZE = 14; 00150 char buf[BUF_SIZE]; 00151 strftime(buf, BUF_SIZE - 1, "%Y-%m-%d", currtime); 00152 return string(buf); 00153 } 00154 00155 //---------------------------------------------------------------------------- 00156