blob: 782cbcde8b74ba0b56cb8eb0cd137890f755a1ae [file] [log] [blame]
Ernesto Posse8a4f2962015-05-12 13:28:46 -04001// umlrttimerspec.cc
2
3/*******************************************************************************
4* Copyright (c) 2014-2015 Zeligsoft (2009) Limited and others.
5* All rights reserved. This program and the accompanying materials
6* are made available under the terms of the Eclipse Public License v1.0
7* which accompanies this distribution, and is available at
8* http://www.eclipse.org/legal/epl-v10.html
9*******************************************************************************/
10
11#include "umlrttimespec.hh"
12#include "basefatal.hh"
13#include <sys/time.h>
14#include <time.h>
15#include <stdlib.h>
16#include <stdio.h>
17
18UMLRTTimespec::UMLRTTimespec( const UMLRTTimespec & tm ) : tv_sec(tm.tv_sec), tv_nsec(tm.tv_nsec) { }
19
20UMLRTTimespec::UMLRTTimespec( long seconds, long nanoseconds ): tv_sec(seconds), tv_nsec(nanoseconds)
21{
22 timespecAdjust(this);
23}
24
25UMLRTTimespec::UMLRTTimespec() { UMLRTTimespec::getClock(this); }
26
27UMLRTTimespec & UMLRTTimespec::operator=( const UMLRTTimespec & tm )
28{
29 tv_sec = tm.tv_sec;
30 tv_nsec = tm.tv_nsec;
31
32 return *this;
33}
34
35bool UMLRTTimespec::operator==( const UMLRTTimespec & tm ) const
36{
37 return (tv_sec == tm.tv_sec) && (tv_nsec == tm.tv_nsec);
38}
39
40bool UMLRTTimespec::operator!=( const UMLRTTimespec & tm ) const
41{
42 return (tv_sec != tm.tv_sec) || (tv_nsec != tm.tv_nsec);
43}
44
45bool UMLRTTimespec::operator<( const UMLRTTimespec & tm ) const
46{
47 if (tv_sec < tm.tv_sec)
48 return true;
49
50 else if (tv_sec == tm.tv_sec)
51 return (tv_nsec < tm.tv_nsec);
52
53 return false;
54}
55
56bool UMLRTTimespec::operator<=( const UMLRTTimespec & tm ) const
57{
58 if (tv_sec < tm.tv_sec)
59 return true;
60
61 else if (tv_sec == tm.tv_sec)
62 return (tv_nsec <= tm.tv_nsec);
63
64 return false;
65}
66
67bool UMLRTTimespec::operator>( const UMLRTTimespec & tm ) const
68{
69 if (tv_sec > tm.tv_sec)
70 return true;
71
72 else if (tv_sec == tm.tv_sec)
73 return (tv_nsec > tm.tv_nsec);
74
75 return false;
76}
77
78bool UMLRTTimespec::operator>=( const UMLRTTimespec & tm ) const
79{
80 if (tv_sec > tm.tv_sec)
81 return true;
82
83 else if (tv_sec == tm.tv_sec)
84 return (tv_nsec >= tm.tv_nsec);
85
86 return false;
87}
88
89// Ensure tv_nsec is always 0..999999999.
90/*static*/ void UMLRTTimespec::timespecAdjust( UMLRTTimespec * tm )
91{
92 // Times must be adjusted after a single add/subtract, so tv_nsec is assumed to be
93 // between -999999999 and 2*999999999 before it is adjusted.
94 // We do a sanity check after the adjustment to confirm our assumptions are correct.
95 if (tm->tv_nsec > ONE_BILLION)
96 {
97 tm->tv_sec += 1;
98 tm->tv_nsec -= ONE_BILLION;
99 }
100 if (tm->tv_nsec < 0)
101 {
102 tm->tv_sec -= 1;
103 tm->tv_nsec += ONE_BILLION;
104 }
105 // For now, we FATAL() if tm->tv_nsec was not sufficiently adjusted.
106 if (tm->tv_nsec > ONE_BILLION)
107 {
108 FATAL("time tv_nsec(%ld) > ONE_BILLION", tm->tv_nsec);
109 }
110 if (tm->tv_nsec < 0)
111 {
112 FATAL("time tv_nsec(%ld) < 0", tm->tv_nsec);
113 }
114}
115
116UMLRTTimespec UMLRTTimespec::operator+( const UMLRTTimespec & tm ) const
117{
118 return UMLRTTimespec(tv_sec + tm.tv_sec, tv_nsec + tm.tv_nsec);
119}
120
121UMLRTTimespec UMLRTTimespec::operator-( const UMLRTTimespec & tm ) const
122{
123 return UMLRTTimespec(tv_sec - tm.tv_sec, tv_nsec - tm.tv_nsec);
124}
125
126UMLRTTimespec & UMLRTTimespec::operator+=( const UMLRTTimespec & tm )
127{
128 tv_sec += tm.tv_sec;
129 tv_nsec += tm.tv_nsec;
130
131 timespecAdjust(this);
132
133 return *this;
134}
135
136UMLRTTimespec & UMLRTTimespec::operator-=( const UMLRTTimespec & tm )
137{
138 tv_sec -= tm.tv_sec;
139 tv_nsec -= tm.tv_nsec;
140
141 timespecAdjust(this);
142
143 return *this;
144}
145
146/*static*/ void UMLRTTimespec::getClock( UMLRTTimespec * tm )
147{
148 // Linux-specific for now.
149 struct timeval tv;
150
151 if (gettimeofday(&tv, NULL) < 0)
152 {
153 FATAL_ERRNO("gettimeofday");
154 }
155 tm->tv_sec = tv.tv_sec;
156 tm->tv_nsec = tv.tv_usec * 1000;
157}
158
159bool UMLRTTimespec::isZeroOrNegative() const
160{
161 return (tv_sec < 0) || ((tv_sec == 0) && (tv_nsec == 0));
162}
163
164char * UMLRTTimespec::toString( char * buffer, int size ) const
165{
166 struct tm from_localtime;
167 const time_t seconds = tv_sec;
168
169 localtime_r( &seconds, &from_localtime );
170
171 size_t length = strftime(buffer, size, "%Y-%m-%d:%H:%M:%S", &from_localtime);
172 long msec = tv_nsec / NANOSECONDS_PER_MILLISECOND;
173 snprintf( &buffer[length], size-length, ".%03ld", msec );
174
175 return buffer;
176}
177
178char * UMLRTTimespec::toStringRelative( char * buffer, int size ) const
179{
180 long int seconds = tv_sec;
181 long int days = seconds / SECONDS_PER_DAY;
182 seconds -= (days * SECONDS_PER_DAY);
183 long int hours = seconds / SECONDS_PER_HOUR;
184 seconds -= (hours * SECONDS_PER_HOUR);
185 long int minutes = seconds / SECONDS_PER_MINUTE;
186 seconds -= (minutes * SECONDS_PER_MINUTE);
187
188 long int msec = tv_nsec / NANOSECONDS_PER_MILLISECOND;
189
190 snprintf( buffer, size, "%ld:%02ld:%02ld:%02ld.%03ld", days, hours, minutes, seconds, msec );
191
192 return buffer;
193}
194
195/*static*/ void UMLRTTimespec::timespecAbsAddMsec( struct timespec * timeout, long msec )
196{
197 clock_gettime(CLOCK_REALTIME, timeout);
198 timeout->tv_sec += (msec / 1000);
199 timeout->tv_nsec += (msec % 1000) * ONE_BILLION;
200 if (timeout->tv_nsec >= ONE_BILLION)
201 {
202 timeout->tv_sec += 1;
203 timeout->tv_nsec -= ONE_BILLION;
204 }
205}
Barry Maher98dd5192015-06-02 15:45:06 -0400206
207static int UMLRTObject_fprintf_UMLRTTimespec( FILE *ostream, const UMLRTObject_class * desc, const void * data )
208{
209 char buf[UMLRTTimespec::TIMESPEC_TOSTRING_SZ];
210
211 return fprintf(ostream, "{UMLRTTimespec %s}", ((const UMLRTTimespec *)data)->toString(buf, sizeof(buf)));
212}
213
214
215static const UMLRTObject_class UMLRTType_UMLRTTimespec_
216= {
217 "UMRTCapsuleId",
218 UMLRTObject_initialize,
219 UMLRTObject_copy,
220 UMLRTObject_decode,
221 UMLRTObject_encode,
222 UMLRTObject_destroy,
223 UMLRTObject_getSize,
224 UMLRTObject_fprintf_UMLRTTimespec,
225 NULL, // super
226 UMLRTOBJECTCLASS_DEFAULT_VERSION, // version
227 UMLRTOBJECTCLASS_DEFAULT_BACKWARDS, // backwards
228 sizeof(UMLRTTimespec),
229 NULL, // fields
230};
231
232const UMLRTObject_class * const UMLRTType_UMLRTTimespec = &UMLRTType_UMLRTTimespec_;