source: box/trunk/lib/common/BoxTime.cpp @ 2845

Revision 2845, 3.2 KB checked in by chris, 17 months ago (diff)

Move accurate sleep code from Test.cpp to BoxTime?, allow requesting times
in microseconds with ShortSleep?(), make safe_sleep() use it.

Rename MILLI_SEC_IN_NANO_SEC to MILLI_SEC_IN_SEC which is what it actually is.

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