1/*
2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// timeflow - abstract view of the flow of time
27//
28// We happily publish both absolute and relative times as floating-point values.
29// Absolute times are off the UNIX Epoch (1/1/1970, midnight). This leaves us about
30// microsecond resolution in Modern Times.
31//
32#ifndef _H_TIMEFLOW
33#define _H_TIMEFLOW
34
35#include <sys/time.h>
36#include <limits.h>
37#include <math.h>	// for MAXFLOAT
38
39
40namespace Security {
41namespace Time {
42
43
44//
45// A Time::Interval is a time difference (distance).
46//
47class Interval {
48    friend class Absolute;
49public:
50    Interval() { }
51    Interval(int seconds)		{ mValue = seconds; }
52    Interval(double seconds)	{ mValue = seconds; }
53    explicit Interval(time_t seconds) { mValue = seconds; }
54
55    Interval &operator += (Interval rel)	{ mValue += rel.mValue; return *this; }
56    Interval &operator -= (Interval rel)	{ mValue -= rel.mValue; return *this; }
57    Interval &operator *= (double f)		{ mValue *= f; return *this; }
58    Interval &operator /= (double f)		{ mValue /= f; return *this; }
59
60    bool operator <  (Interval other) const	{ return mValue < other.mValue; }
61    bool operator <= (Interval other) const	{ return mValue <= other.mValue; }
62    bool operator >  (Interval other) const	{ return mValue > other.mValue; }
63    bool operator >= (Interval other) const	{ return mValue >= other.mValue; }
64    bool operator == (Interval other) const	{ return mValue == other.mValue; }
65    bool operator != (Interval other) const	{ return mValue != other.mValue; }
66
67    // express as (fractions of) seconds, milliseconds, or microseconds
68    double seconds() const					{ return mValue; }
69    double mSeconds() const					{ return mValue * 1E3; }
70    double uSeconds() const					{ return mValue * 1E6; }
71
72    // struct timeval is sometimes used for time intervals, but not often - so be explicit
73    struct timeval timevalInterval() const;
74
75private:
76    double mValue;
77};
78
79
80//
81// A Time::Absolute is a moment in time.
82//
83class Absolute {
84    friend class Interval;
85    friend Interval operator - (Absolute, Absolute);
86    friend Absolute now();
87    friend Absolute bigBang();
88    friend Absolute heatDeath();
89public:
90    Absolute() { }						// uninitialized
91    Absolute(time_t t) { mValue = t; }	// from time_t
92    Absolute(const struct timeval &tv);	// from timeval
93	Absolute(const struct timespec &ts); // from timespec
94
95    // *crement operators
96    Absolute &operator += (Interval rel)	{ mValue += rel.mValue; return *this; }
97    Absolute &operator -= (Interval rel)	{ mValue -= rel.mValue; return *this; }
98
99    // comparisons
100    bool operator <  (Absolute other) const	{ return mValue < other.mValue; }
101    bool operator <= (Absolute other) const	{ return mValue <= other.mValue; }
102    bool operator >  (Absolute other) const	{ return mValue > other.mValue; }
103    bool operator >= (Absolute other) const	{ return mValue >= other.mValue; }
104    bool operator == (Absolute other) const	{ return mValue == other.mValue; }
105    bool operator != (Absolute other) const	{ return mValue != other.mValue; }
106
107    // express as conventional (absolute!) time measures
108    operator struct timeval() const;
109	operator struct timespec() const;
110    operator time_t () const				{ return time_t(mValue); }
111
112    // internal form for debugging ONLY
113    double internalForm() const				{ return mValue; }
114
115private:
116    double mValue;
117
118    Absolute(double value) : mValue(value) { }
119};
120
121
122//
123// Time::now produces the current time
124//
125Absolute now();						// get "now"
126
127
128//
129// Time::resolution(when) gives a conservative estimate of the available resolution
130// at a given time.
131//
132Interval resolution(Absolute at);	// estimate available resolution at given time
133
134
135//
136// Some useful "constants"
137//
138inline Absolute bigBang()				{ return -MAXFLOAT; }
139inline Absolute heatDeath()				{ return +MAXFLOAT; }
140
141
142
143//
144// More inline arithmetic
145//
146inline Interval operator + (Interval r, Interval r2)	{ r += r2; return r; }
147inline Interval operator - (Interval r, Interval r2)	{ r -= r2; return r; }
148inline Interval operator * (Interval r, double f)		{ r *= f; return r; }
149inline Interval operator / (Interval r, double f)		{ r /= f; return r; }
150
151inline Absolute operator + (Absolute a, Interval r)		{ return a += r; }
152inline Absolute operator + (Interval r, Absolute a)		{ return a += r; }
153inline Absolute operator - (Absolute a, Interval r)		{ return a -= r; }
154
155inline Interval operator - (Absolute t1, Absolute t0)
156{ return t1.mValue - t0.mValue; }
157
158
159}	// end namespace Time
160}	// end namespace Security
161
162#endif //_H_TIMEFLOW
163