1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1999-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 #if ! defined (octave_oct_time_h)
27 #define octave_oct_time_h 1
28
29 #include "octave-config.h"
30
31 #include <ctime>
32
33 #include <iosfwd>
34 #include <string>
35
36 static inline double
as_double(time_t sec,long usec)37 as_double (time_t sec, long usec)
38 {
39 // Unix time will be exactly representable as a double for more than
40 // 100 million years, so no worry there, and microseconds has a
41 // range of 0-1e6, so we are safe there as well.
42
43 return (static_cast<double> (sec) + static_cast<double> (usec) / 1.0e6);
44 }
45
46 namespace octave
47 {
48 namespace sys
49 {
50 class base_tm;
51
52 class
53 OCTAVE_API
54 time
55 {
56 public:
57
time(void)58 time (void)
59 : ot_unix_time (0), ot_usec (0) { stamp (); }
60
time(time_t t)61 time (time_t t)
62 : ot_unix_time (t), ot_usec (0) { }
63
time(time_t t,long us)64 time (time_t t, long us)
65 : ot_unix_time (t), ot_usec ()
66 {
67 long rem, extra;
68
69 if (us >= 0)
70 {
71 rem = us % 1000000;
72 extra = (us - rem) / 1000000;
73 }
74 else
75 {
76 us = -us;
77 rem = us % 1000000;
78 extra = - (1 + (us - rem) / 1000000);
79 rem = 1000000 - us % 1000000;
80 }
81
82 ot_usec = rem;
83 ot_unix_time += extra;
84 }
85
86 time (double d);
87
88 time (const base_tm& tm);
89
time(const time & ot)90 time (const time& ot)
91 : ot_unix_time (ot.ot_unix_time), ot_usec (ot.ot_usec) { }
92
93 time& operator = (const time& ot)
94 {
95 if (this != &ot)
96 {
97 ot_unix_time = ot.ot_unix_time;
98 ot_usec = ot.ot_usec;
99 }
100
101 return *this;
102 }
103
104 ~time (void) = default;
105
106 void stamp (void);
107
double_value(void)108 double double_value (void) const
109 {
110 return as_double (ot_unix_time, ot_usec);
111 }
112
unix_time(void)113 time_t unix_time (void) const { return ot_unix_time; }
114
usec(void)115 long usec (void) const { return ot_usec; }
116
117 std::string ctime (void) const;
118
119 friend std::ostream& operator << (std::ostream& os, const time& ot);
120
121 private:
122
123 // Seconds since the epoch.
124 time_t ot_unix_time;
125
126 // Additional microseconds.
127 long ot_usec;
128 };
129
130 inline bool
131 operator == (const time& t1, const time& t2)
132 {
133 return (t1.unix_time () == t2.unix_time () && t1.usec () == t2.usec ());
134 }
135
136 inline bool
137 operator != (const time& t1, const time& t2)
138 {
139 return ! (t1 == t2);
140 }
141
142 inline bool
143 operator < (const time& t1, const time& t2)
144 {
145 if (t1.unix_time () < t2.unix_time ())
146 return true;
147 else if (t1.unix_time () > t2.unix_time ())
148 return false;
149 else if (t1.usec () < t2.usec ())
150 return true;
151 else
152 return false;
153 }
154
155 inline bool
156 operator <= (const time& t1, const time& t2)
157 {
158 return (t1 < t2 || t1 == t2);
159 }
160
161 inline bool
162 operator > (const time& t1, const time& t2)
163 {
164 if (t1.unix_time () > t2.unix_time ())
165 return true;
166 else if (t1.unix_time () < t2.unix_time ())
167 return false;
168 else if (t1.usec () > t2.usec ())
169 return true;
170 else
171 return false;
172 }
173
174 inline bool
175 operator >= (const time& t1, const time& t2)
176 {
177 return (t1 > t2 || t1 == t2);
178 }
179
180 inline time
181 operator + (const time& t1, const time& t2)
182 {
183 return time (t1.unix_time () + t2.unix_time (),
184 t1.usec () + t2.usec ());
185 }
186
187 class
188 OCTAVE_API
189 base_tm
190 {
191 public:
192
base_tm(void)193 base_tm (void)
194 : m_usec (0), m_sec (0), m_min (0), m_hour (0),
195 m_mday (0), m_mon (0), m_year (0), m_wday (0),
196 m_yday (0), m_isdst (0), m_gmtoff (0), m_zone ("unknown")
197 { }
198
base_tm(const base_tm & tm)199 base_tm (const base_tm& tm)
200 : m_usec (tm.m_usec), m_sec (tm.m_sec), m_min (tm.m_min),
201 m_hour (tm.m_hour), m_mday (tm.m_mday), m_mon (tm.m_mon),
202 m_year (tm.m_year), m_wday (tm.m_wday), m_yday (tm.m_yday),
203 m_isdst (tm.m_isdst), m_gmtoff (tm.m_gmtoff), m_zone (tm.m_zone)
204 { }
205
206 base_tm& operator = (const base_tm& tm)
207 {
208 if (this != &tm)
209 {
210 m_usec = tm.m_usec;
211 m_sec = tm.m_sec;
212 m_min = tm.m_min;
213 m_hour = tm.m_hour;
214 m_mday = tm.m_mday;
215 m_mon = tm.m_mon;
216 m_year = tm.m_year;
217 m_wday = tm.m_wday;
218 m_yday = tm.m_yday;
219 m_isdst = tm.m_isdst;
220 m_gmtoff = tm.m_gmtoff;
221 m_zone = tm.m_zone;
222 }
223
224 return *this;
225 }
226
227 virtual ~base_tm (void) = default;
228
usec(void)229 int usec (void) const { return m_usec; }
sec(void)230 int sec (void) const { return m_sec; }
min(void)231 int min (void) const { return m_min; }
hour(void)232 int hour (void) const { return m_hour; }
mday(void)233 int mday (void) const { return m_mday; }
mon(void)234 int mon (void) const { return m_mon; }
year(void)235 int year (void) const { return m_year; }
wday(void)236 int wday (void) const { return m_wday; }
yday(void)237 int yday (void) const { return m_yday; }
isdst(void)238 int isdst (void) const { return m_isdst; }
gmtoff(void)239 long gmtoff (void) const { return m_gmtoff; }
zone(void)240 std::string zone (void) const { return m_zone; }
241
242 base_tm& usec (int v);
243 base_tm& sec (int v);
244 base_tm& min (int v);
245 base_tm& hour (int v);
246 base_tm& mday (int v);
247 base_tm& mon (int v);
248 base_tm& year (int v);
249 base_tm& wday (int v);
250 base_tm& yday (int v);
251 base_tm& isdst (int v);
252 base_tm& gmtoff (long v);
253 base_tm& zone (const std::string& s);
254
255 std::string strftime (const std::string& fmt) const;
256
asctime(void)257 std::string asctime (void) const
258 { return strftime ("%a %b %d %H:%M:%S %Y\n"); }
259
260 protected:
261
262 // Microseconds after the second (0, 999999).
263 int m_usec;
264
265 // Seconds after the minute (0, 61).
266 int m_sec;
267
268 // Minutes after the hour (0, 59).
269 int m_min;
270
271 // Hours since midnight (0, 23).
272 int m_hour;
273
274 // Day of the month (1, 31).
275 int m_mday;
276
277 // Months since January (0, 11).
278 int m_mon;
279
280 // Years since 1900.
281 int m_year;
282
283 // Days since Sunday (0, 6).
284 int m_wday;
285
286 // Days since January 1 (0, 365).
287 int m_yday;
288
289 // Daylight saving time flag.
290 int m_isdst;
291
292 // Time zone.
293 long m_gmtoff;
294
295 // Time zone.
296 std::string m_zone;
297
298 void init (void *p);
299 };
300
301 class
302 OCTAVE_API
303 localtime : public base_tm
304 {
305 public:
306
localtime(void)307 localtime (void)
308 : base_tm () { init (time ()); }
309
localtime(const time & ot)310 localtime (const time& ot)
311 : base_tm () { init (ot); }
312
localtime(const localtime & t)313 localtime (const localtime& t)
314 : base_tm (t) { }
315
316 localtime& operator = (const localtime& t)
317 {
318 base_tm::operator = (t);
319 return *this;
320 }
321
322 ~localtime (void) = default;
323
324 private:
325
326 void init (const time& ot);
327 };
328
329 class
330 OCTAVE_API
331 gmtime : public base_tm
332 {
333 public:
334
gmtime(void)335 gmtime (void)
336 : base_tm () { init (time ()); }
337
gmtime(const time & ot)338 gmtime (const time& ot)
339 : base_tm () { init (ot); }
340
341 gmtime& operator = (const gmtime& t)
342 {
343 base_tm::operator = (t);
344 return *this;
345 }
346
347 ~gmtime (void) = default;
348
349 private:
350
351 void init (const time& ot);
352 };
353
354 class
355 OCTAVE_API
356 strptime : public base_tm
357 {
358 public:
359
strptime(const std::string & str,const std::string & fmt)360 strptime (const std::string& str, const std::string& fmt)
361 : base_tm (), nchars (0)
362 {
363 init (str, fmt);
364 }
365
strptime(const strptime & s)366 strptime (const strptime& s)
367 : base_tm (s), nchars (s.nchars) { }
368
369 strptime& operator = (const strptime& s)
370 {
371 base_tm::operator = (s);
372 nchars = s.nchars;
373 return *this;
374 }
375
characters_converted(void)376 int characters_converted (void) const { return nchars; }
377
378 ~strptime (void) = default;
379
380 private:
381
382 int nchars;
383
384 void init (const std::string& str, const std::string& fmt);
385 };
386
387 class
388 OCTAVE_API
389 cpu_time
390 {
391 public:
392
393 friend class resource_usage;
394
cpu_time(void)395 cpu_time (void)
396 : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0)
397 {
398 stamp ();
399 }
400
cpu_time(const cpu_time & tm)401 cpu_time (const cpu_time& tm)
402 : m_usr_sec (tm.m_usr_sec), m_sys_sec (tm.m_sys_sec),
403 m_usr_usec (tm.m_usr_usec), m_sys_usec (tm.m_sys_usec)
404 { }
405
406 cpu_time& operator = (const cpu_time& tm)
407 {
408 if (&tm != this)
409 {
410 m_usr_sec = tm.m_usr_sec;
411 m_sys_sec = tm.m_sys_sec;
412 m_usr_usec = tm.m_usr_usec;
413 m_sys_usec = tm.m_sys_usec;
414 }
415
416 return *this;
417 }
418
419 void stamp (void);
420
user(void)421 double user (void) const
422 {
423 return as_double (m_usr_sec, m_usr_usec);
424 }
425
system(void)426 double system (void) const
427 {
428 return as_double (m_sys_sec, m_sys_usec);
429 }
430
user_sec(void)431 time_t user_sec (void) const { return m_usr_sec; }
user_usec(void)432 long user_usec (void) const { return m_usr_usec; }
433
system_sec(void)434 time_t system_sec (void) const { return m_sys_sec; }
system_usec(void)435 long system_usec (void) const { return m_sys_usec; }
436
437 private:
438
439 time_t m_usr_sec;
440 time_t m_sys_sec;
441
442 long m_usr_usec;
443 long m_sys_usec;
444
cpu_time(time_t usr_sec,time_t sys_sec,long usr_usec,long sys_usec)445 cpu_time (time_t usr_sec, time_t sys_sec, long usr_usec, long sys_usec)
446 : m_usr_sec (usr_sec), m_sys_sec (sys_sec),
447 m_usr_usec (usr_usec), m_sys_usec (sys_usec)
448 { }
449 };
450
451 class
452 resource_usage
453 {
454 public:
455
resource_usage(void)456 resource_usage (void)
457 : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0),
458 m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0),
459 m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0),
460 m_nsignals (0), m_nvcsw (0), m_nivcsw (0)
461 {
462 stamp ();
463 }
464
resource_usage(const resource_usage & ru)465 resource_usage (const resource_usage& ru)
466 : m_cpu (ru.m_cpu), m_maxrss (ru.m_maxrss),
467 m_ixrss (ru.m_ixrss), m_idrss (ru.m_idrss),
468 m_isrss (ru.m_isrss), m_minflt (ru.m_minflt),
469 m_majflt (ru.m_majflt), m_nswap (ru.m_nswap),
470 m_inblock (ru.m_inblock), m_oublock (ru.m_oublock),
471 m_msgsnd (ru.m_msgsnd), m_msgrcv (ru.m_msgrcv),
472 m_nsignals (ru.m_nsignals), m_nvcsw (ru.m_nvcsw),
473 m_nivcsw (ru.m_nivcsw)
474 { }
475
476 resource_usage& operator = (const resource_usage& ru)
477 {
478 if (&ru != this)
479 {
480 m_cpu = ru.m_cpu;
481
482 m_maxrss = ru.m_maxrss;
483 m_ixrss = ru.m_ixrss;
484 m_idrss = ru.m_idrss;
485 m_isrss = ru.m_isrss;
486 m_minflt = ru.m_minflt;
487 m_majflt = ru.m_majflt;
488 m_nswap = ru.m_nswap;
489 m_inblock = ru.m_inblock;
490 m_oublock = ru.m_oublock;
491 m_msgsnd = ru.m_msgsnd;
492 m_msgrcv = ru.m_msgrcv;
493 m_nsignals = ru.m_nsignals;
494 m_nvcsw = ru.m_nvcsw;
495 m_nivcsw = ru.m_nivcsw;
496 }
497
498 return *this;
499 }
500
501 void stamp (void);
502
cpu(void)503 cpu_time cpu (void) const { return m_cpu; }
504
maxrss(void)505 long maxrss (void) const { return m_maxrss; }
ixrss(void)506 long ixrss (void) const { return m_ixrss; }
idrss(void)507 long idrss (void) const { return m_idrss; }
isrss(void)508 long isrss (void) const { return m_isrss; }
minflt(void)509 long minflt (void) const { return m_minflt; }
majflt(void)510 long majflt (void) const { return m_majflt; }
nswap(void)511 long nswap (void) const { return m_nswap; }
inblock(void)512 long inblock (void) const { return m_inblock; }
oublock(void)513 long oublock (void) const { return m_oublock; }
msgsnd(void)514 long msgsnd (void) const { return m_msgsnd; }
msgrcv(void)515 long msgrcv (void) const { return m_msgrcv; }
nsignals(void)516 long nsignals (void) const { return m_nsignals; }
nvcsw(void)517 long nvcsw (void) const { return m_nvcsw; }
nivcsw(void)518 long nivcsw (void) const { return m_nivcsw; }
519
520 private:
521
522 cpu_time m_cpu;
523
524 long m_maxrss;
525 long m_ixrss;
526 long m_idrss;
527 long m_isrss;
528 long m_minflt;
529 long m_majflt;
530 long m_nswap;
531 long m_inblock;
532 long m_oublock;
533 long m_msgsnd;
534 long m_msgrcv;
535 long m_nsignals;
536 long m_nvcsw;
537 long m_nivcsw;
538 };
539 }
540 }
541
542 #endif
543