Go to the documentation of this file.00001 #include "rtc/rtcTime.h"
00002 #include <cmath>
00003 #include <time.h>
00004 #include <iomanip>
00005 #include <stdexcept>
00006 #include <time.h>
00007
00008 #include <boost/thread/mutex.hpp>
00009
00010 #ifndef WIN32
00011 #if POSIX_TIMERS <= 0
00012 #include <sys/time.h>
00013 #endif
00014 #else
00015 #include <sys/timeb.h>
00016
00017 #endif
00018
00019 using namespace rtc;
00020 using namespace std;
00021
00022
00023 rtc::Time rtc::Time::sim_time_(0, 0);
00024 bool rtc::Time::use_system_time_(true);
00025
00026 const Duration rtc::DURATION_MAX(INT_MAX, 999999999);
00027 const Duration rtc::DURATION_MIN(INT_MIN, 0);
00028
00029
00030
00031 static bool g_stopped(false);
00032
00033
00034
00035 static boost::mutex g_sim_time_mutex;
00036
00037 void getWallTime(uint32_t& sec, uint32_t& nsec)
00038 {
00039 #ifndef WIN32
00040 #if POSIX_TIMERS > 0
00041 struct timespec start;
00042 clock_gettime(CLOCK_REALTIME, &start);
00043 sec = start.tv_sec;
00044 nsec = start.tv_nsec;
00045 #else
00046 struct timeval timeofday;
00047 gettimeofday(&timeofday,NULL);
00048 sec = timeofday.tv_sec;
00049 nsec = timeofday.tv_usec * 1000;
00050 #endif
00051 #else
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static LARGE_INTEGER cpu_freq, init_cpu_time;
00062 static Time start_time;
00063 if (start_time.isZero())
00064 {
00065 QueryPerformanceFrequency(&cpu_freq);
00066 if (cpu_freq.QuadPart == 0)
00067 {
00068 rtc_verbose("woah! this system (for whatever reason) does not support the "
00069 "high-performance timing API. ur done.\n");
00070 abort();
00071 }
00072 QueryPerformanceCounter(&init_cpu_time);
00073
00074 FILETIME ft;
00075 GetSystemTimeAsFileTime(&ft);
00076 LARGE_INTEGER start_li;
00077 start_li.LowPart = ft.dwLowDateTime;
00078 start_li.HighPart = ft.dwHighDateTime;
00079
00080
00081 #ifdef _MSC_VER
00082 start_li.QuadPart -= 116444736000000000Ui64;
00083 #else
00084 start_li.QuadPart -= 116444736000000000ULL;
00085 #endif
00086 start_time.sec = (uint32_t)(start_li.QuadPart / 10000000);
00087 start_time.nsec = (start_li.LowPart % 10000000) * 100;
00088 }
00089 LARGE_INTEGER cur_time;
00090 QueryPerformanceCounter(&cur_time);
00091 LARGE_INTEGER delta_cpu_time;
00092 delta_cpu_time.QuadPart = cur_time.QuadPart - init_cpu_time.QuadPart;
00093
00094
00095 double d_delta_cpu_time = delta_cpu_time.QuadPart / (double)cpu_freq.QuadPart;
00096 Time t(start_time + Duration(d_delta_cpu_time));
00097
00098 sec = t.sec;
00099 nsec = t.nsec;
00100 #endif
00101 }
00102
00103 Time Time::now()
00104 {
00105 if (!use_system_time_)
00106 {
00107 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00108 Time t = sim_time_;
00109 return t;
00110 }
00111
00112 Time t;
00113 getWallTime(t.sec, t.nsec);
00114
00115 return t;
00116 }
00117
00118 void Time::setNow(const Time& new_now)
00119 {
00120 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00121
00122 sim_time_ = new_now;
00123 use_system_time_ = false;
00124 }
00125
00126 void Time::init()
00127 {
00128 g_stopped = false;
00129 use_system_time_ = true;
00130 }
00131
00132 void Time::shutdown()
00133 {
00134 g_stopped = true;
00135 }
00136
00137 ostream &rtc::operator<<(ostream& os, const Time &rhs)
00138 {
00139 os << rhs.sec << "." << setw(9) << setfill('0') << rhs.nsec;
00140 return os;
00141 }
00142
00143 ostream &rtc::operator<<(ostream& os, const Duration& rhs)
00144 {
00145 os << rhs.sec << "." << setw(9) << setfill('0') << rhs.nsec;
00146 return os;
00147 }
00148
00149 bool Time::sleepUntil(const Time& end)
00150 {
00151 if (Time::useSystemTime())
00152 {
00153 Duration d(end - Time::now());
00154 if (d > Duration(0))
00155 {
00156 return d.sleep();
00157 }
00158
00159 return true;
00160 }
00161 else
00162 {
00163 Time start = Time::now();
00164 struct timespec ts = {0, 1000000};
00165 while (!g_stopped && (Time::now() < end))
00166 {
00167
00168 #ifdef _WIN32
00169 Sleep(1);
00170 #else
00171 if (nanosleep(&ts, NULL))
00172 {
00173 return false;
00174 }
00175 #endif
00176
00177 if (Time::now() < start)
00178 {
00179 return false;
00180 }
00181 }
00182
00183 return true;
00184 }
00185 }
00186
00187 bool WallTime::sleepUntil(const WallTime& end)
00188 {
00189 WallDuration d(end - WallTime::now());
00190 if (d > WallDuration(0))
00191 {
00192 return d.sleep();
00193 }
00194
00195 return true;
00196 }
00197
00198 bool wallSleep(uint32_t sec, uint32_t nsec)
00199 {
00200 #ifdef _WIN32
00201 Sleep(sec*1000+nsec);
00202 #else
00203 struct timespec ts = {sec, nsec};
00204 struct timespec rem;
00205 while (nanosleep(&ts, &rem) && !g_stopped)
00206 {
00207 ts = rem;
00208 }
00209 #endif
00210
00211 return !g_stopped;
00212 }
00213
00214 bool Duration::sleep() const
00215 {
00216 if (Time::useSystemTime())
00217 {
00218 return wallSleep(sec, nsec);
00219 }
00220 else
00221 {
00222 Time start = Time::now();
00223 Time end = start + *this;
00224 while (!g_stopped && (Time::now() < end))
00225 {
00226 wallSleep(0, 1000000);
00227
00228 if (Time::now() < start)
00229 {
00230 return false;
00231 }
00232 }
00233
00234 return true;
00235 }
00236 }
00237
00238 ostream &rtc::operator<<(ostream& os, const WallTime &rhs)
00239 {
00240 os << rhs.sec << "." << setw(9) << setfill('0') << rhs.nsec;
00241 return os;
00242 }
00243
00244 WallTime WallTime::now()
00245 {
00246 WallTime t;
00247 getWallTime(t.sec, t.nsec);
00248
00249 return t;
00250 }
00251
00252 ostream &rtc::operator<<(ostream& os, const WallDuration& rhs)
00253 {
00254 os << rhs.sec << "." << setw(9) << setfill('0') << rhs.nsec;
00255 return os;
00256 }
00257
00258 bool WallDuration::sleep() const
00259 {
00260 return wallSleep(sec, nsec);
00261 }