1 /*****************************************************************************\
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 1995-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
15 #include "earth_time.h"
16 #include "time_stamp.h"
18 #include <application/windoze_helper.h>
19 #include <basis/environment.h>
20 #include <basis/mutex.h>
21 #include <loggers/program_wide_logger.h>
25 // #define _WINSOCKAPI_ // make windows.h happy about winsock.
26 // #include <winsock2.h> // timeval.
29 //#define DEBUG_TIME_STAMP
31 #ifdef DEBUG_TIME_STAMP
32 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
33 using namespace loggers;
36 using namespace basis;
40 static mutex &__uptime_synchronizer() {
41 static mutex uptiming_syncher;
42 return uptiming_syncher;
45 basis::astring time_stamp::notarize(bool add_space)
47 const time_locus the_time = now();
49 the_time.text_form_long(to_return, clock_time::MILITARY | clock_time::MILLISECONDS);
50 if (add_space) to_return += " ";
54 time_stamp::time_stamp() : c_stamp(0) { fill_in_time(); }
56 time_stamp::time_stamp(time_representation offset)
57 : c_stamp(0) { reset(offset); }
59 void time_stamp::reset() { fill_in_time(); }
61 astring time_stamp::text_form(stamp_display_style style) const
63 time_representation stump = c_stamp;
65 if (style == STAMP_RELATIVE) {
66 // adjust the returned time by subtracting the current time.
67 stump -= get_time_now();
68 if (negative(stump)) {
69 // if we're negative, just note that the stamp is in the past.
71 stump = absolute_value(stump);
74 time_representation divisor = 3600 * SECOND_ms;
75 basis::un_int hours = basis::un_int(stump / divisor);
76 stump -= divisor * time_representation(hours);
78 basis::un_int minutes = basis::un_int(stump / divisor);
79 stump -= divisor * time_representation(minutes);
81 basis::un_int seconds = basis::un_int(stump / divisor);
82 stump -= divisor * time_representation(seconds);
83 basis::un_int milliseconds = basis::un_int(stump);
84 // make absolutely sure we are between 0 and 999.
88 bool did_hours = false;
90 to_return += astring(astring::SPRINTF, "%uh:", hours);
93 if (minutes || did_hours)
94 to_return += astring(astring::SPRINTF, "%02um:", minutes);
95 to_return += astring(astring::SPRINTF, "%02us.%03u", seconds, milliseconds);
96 if (style == STAMP_RELATIVE) {
97 if (past) to_return += " ago";
98 else to_return += " from now";
103 void time_stamp::fill_in_time()
105 time_representation current = get_time_now();
106 c_stamp = current; // reset our own time now.
109 void time_stamp::reset(time_representation offset)
115 time_stamp::time_representation time_stamp::get_time_now()
116 { return rolling_uptime(); }
118 const double __rollover_point = 2.0 * MAXINT32;
119 // this number is our rollover point for 32 bit integers.
121 double time_stamp::rolling_uptime()
123 auto_synchronizer l(__uptime_synchronizer());
124 // protect our rollover records.
126 static basis::un_int __last_ticks = 0;
127 static int __rollovers = 0;
129 basis::un_int ticks_up = environment::system_uptime();
130 // acquire the current uptime as a 32 bit unsigned int.
132 if (ticks_up < __last_ticks) {
133 // rollover happened. increment our tracker.
136 __last_ticks = ticks_up;
138 return double(__rollovers) * __rollover_point + double(ticks_up);
141 void time_stamp::fill_timeval_ms(struct timeval &time_out, int duration)
143 FUNCDEF("fill_timeval_ms");
144 // timeval has tv_sec=seconds, tv_usec=microseconds.
146 // duration is immediate for the check; just a quick poll.
148 time_out.tv_usec = 0;
149 #ifdef DEBUG_TIME_STAMP
150 LOG("no duration specified");
153 // a non-zero duration means we need to compute secs and usecs.
154 time_out.tv_sec = duration / 1000;
155 // set the number of seconds from the input in milliseconds.
156 duration -= time_out.tv_sec * 1000;
157 // now take out the chunk we've already recorded as seconds.
158 time_out.tv_usec = duration * 1000;
159 // set the number of microseconds from the remaining milliseconds.
160 #ifdef DEBUG_TIME_STAMP
161 LOG(a_sprintf("duration of %d ms went to %d sec and %d usec.", duration,
162 time_out.tv_sec, time_out.tv_usec));