1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// --------------------------------------------------------------------------
//
// File
// Name: BoxTime.cpp
// Purpose: Time for the box
// Created: 2003/10/08
//
// --------------------------------------------------------------------------
#include "Box.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#include <errno.h>
#include <string.h>
#include "BoxTime.h"
#include "MemLeakFindOn.h"
// --------------------------------------------------------------------------
//
// Function
// Name: GetCurrentBoxTime()
// Purpose: Returns the current time as a box time.
// (1 sec precision, or better if supported by system)
// Created: 2003/10/08
//
// --------------------------------------------------------------------------
box_time_t GetCurrentBoxTime()
{
#ifdef HAVE_GETTIMEOFDAY
struct timeval tv;
if (gettimeofday(&tv, NULL) != 0)
{
BOX_LOG_SYS_ERROR("Failed to gettimeofday(), "
"dropping precision");
}
else
{
box_time_t time_now = (tv.tv_sec * MICRO_SEC_IN_SEC_LL) + tv.tv_usec;
return time_now;
}
#elif WIN32
// There's no Win32 API function that returns the current time as a UNIX timestamp with
// sub-second precision. So we use time(0) and add the fractional part from
// GetSystemTime() in the hope that the difference between these two (if any) is a whole
// number of seconds.
box_time_t time_now = SecondsToBoxTime(time(0));
SYSTEMTIME system_time;
GetSystemTime(&system_time);
time_now += MilliSecondsToBoxTime(system_time.wMilliseconds);
return time_now;
#endif
return SecondsToBoxTime(time(0));
}
std::string FormatTime(box_time_t time, bool includeDate, bool showMicros)
{
std::ostringstream buf;
time_t seconds = BoxTimeToSeconds(time);
int micros = BoxTimeToMicroSeconds(time) % MICRO_SEC_IN_SEC;
struct tm tm_now, *tm_ptr = &tm_now;
#ifdef WIN32
if ((tm_ptr = localtime(&seconds)) != NULL)
#else
if (localtime_r(&seconds, &tm_now) != NULL)
#endif
{
buf << std::setfill('0');
if (includeDate)
{
buf << std::setw(4) << (tm_ptr->tm_year + 1900) << "-" <<
std::setw(2) << (tm_ptr->tm_mon + 1) << "-" <<
std::setw(2) << (tm_ptr->tm_mday) << " ";
}
buf << std::setw(2) << tm_ptr->tm_hour << ":" <<
std::setw(2) << tm_ptr->tm_min << ":" <<
std::setw(2) << tm_ptr->tm_sec;
if (showMicros)
{
buf << "." << std::setw(3) << (int)(micros / 1000);
}
}
else
{
buf << strerror(errno);
}
return buf.str();
}
// --------------------------------------------------------------------------
//
// Function
// Name: ShortSleep(box_time_t duration)
// Purpose: Sleeps for the specified duration as accurately
// and efficiently as possible.
// Created: 2011/01/11
//
// --------------------------------------------------------------------------
void ShortSleep(box_time_t duration, bool logDuration)
{
if(logDuration)
{
BOX_TRACE("Sleeping for " << BOX_FORMAT_MICROSECONDS(duration));
}
#ifdef WIN32
Sleep(BoxTimeToMilliSeconds(duration));
#else
struct timespec ts;
memset(&ts, 0, sizeof(ts));
ts.tv_sec = duration / MICRO_SEC_IN_SEC;
ts.tv_nsec = (duration % MICRO_SEC_IN_SEC) * 1000;
box_time_t start_time = GetCurrentBoxTime();
while (nanosleep(&ts, &ts) == -1 && errno == EINTR)
{
// FIXME evil hack for OSX, where ts.tv_sec contains
// a negative number interpreted as unsigned 32-bit
// when nanosleep() returns later than expected.
int32_t secs = (int32_t) ts.tv_sec;
int64_t remain_ns = ((int64_t)secs * 1000000000) + ts.tv_nsec;
if (remain_ns < 0)
{
BOX_WARNING("nanosleep interrupted " <<
((float)(0 - remain_ns) / 1000000000) <<
" secs late");
return;
}
BOX_TRACE("nanosleep interrupted with " << remain_ns <<
" nanosecs remaining, sleeping again");
}
box_time_t sleep_time = GetCurrentBoxTime() - start_time;
BOX_TRACE("Actually slept for " << BOX_FORMAT_MICROSECONDS(sleep_time) <<
", was aiming for " << BOX_FORMAT_MICROSECONDS(duration));
#endif
}
|