1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.event
;
17 * <b><u>TmfTimestamp</u></b>
19 * The fundamental time reference in the TMF.
21 * It provides a generic timestamp implementation in its most basic form:
23 * <li>timestamp = [value] * 10**[scale] +/- [precision]
27 * <li>[value] is an unstructured integer value
28 * <li>[scale] is the magnitude of the value wrt some application-specific
29 * base unit (e.g. the second)
30 * <li>[precision] indicates the error on the value (useful for comparing
31 * timestamps in different scales). Default: 0.
36 * To allow synchronization of timestamps from different reference clocks,
37 * there is a possibility to "adjust" the timestamp by changing its scale
38 * (traces of different time scale) and/or by adding an offset to its value
39 * (clock drift between traces).
41 * Notice that the adjusted timestamp value could be negative e.g. for events
42 * that occurred before t0 wrt the reference clock.
44 public class TmfTimestamp
implements Cloneable
{
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
50 protected long fValue
; // The timestamp raw value
51 protected byte fScale
; // The time scale
52 protected long fPrecision
; // The value precision (tolerance)
54 // ------------------------------------------------------------------------
56 // ------------------------------------------------------------------------
58 // The beginning and end of time
59 public static final TmfTimestamp BigBang
= new TmfTimestamp(Long
.MIN_VALUE
, Byte
.MAX_VALUE
, 0);
60 public static final TmfTimestamp BigCrunch
= new TmfTimestamp(Long
.MAX_VALUE
, Byte
.MAX_VALUE
, 0);
61 public static final TmfTimestamp Zero
= new TmfTimestamp(0, (byte) 0, 0);
64 * A java <code>long</code> has a maximum of 19 significant digits.
65 * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807)
67 * It is therefore useless to try to synchronize 2 timestamps whose
68 * difference in scale exceeds that value.
70 private int MAX_SCALING
= 19;
72 // ------------------------------------------------------------------------
74 // ------------------------------------------------------------------------
79 public TmfTimestamp() {
84 * Simple constructor with value only
86 public TmfTimestamp(long value
) {
87 this(value
, (byte) 0, 0);
91 * Simple constructor with value and scale
96 public TmfTimestamp(long value
, byte scale
) {
97 this(value
, scale
, 0);
101 * Constructor with value, scale and precision
107 public TmfTimestamp(long value
, byte scale
, long precision
) {
110 fPrecision
= Math
.abs(precision
);
118 public TmfTimestamp(TmfTimestamp other
) {
120 throw new IllegalArgumentException();
121 fValue
= other
.fValue
;
122 fScale
= other
.fScale
;
123 fPrecision
= other
.fPrecision
;
126 // ------------------------------------------------------------------------
128 // ------------------------------------------------------------------------
131 * @return the timestamp value
133 public long getValue() {
138 * @return the timestamp scale
140 public byte getScale() {
145 * @return the timestamp value precision
147 public long getPrecision() {
151 // ------------------------------------------------------------------------
153 // ------------------------------------------------------------------------
156 * Return a shifted and scaled timestamp.
158 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
159 * The main reason is that the 64 bits value starts to lose any significance
160 * meaning beyond that scale difference and it's not even worth the trouble
161 * to switch to BigDecimal arithmetics.
163 * @param offset the shift value (in the same scale as newScale)
164 * @param newScale the new timestamp scale
165 * @return the synchronized timestamp in the new scale
166 * @throws ArithmeticException
168 public TmfTimestamp
synchronize(long offset
, byte newScale
) throws ArithmeticException
{
170 long newValue
= fValue
;
171 long newPrecision
= fPrecision
;
173 // Determine the scaling factor
174 if (fScale
!= newScale
) {
175 int scaleDiff
= Math
.abs(fScale
- newScale
);
176 // Let's try to be realistic...
177 if (scaleDiff
> MAX_SCALING
) {
178 throw new ArithmeticException("Scaling exception");
181 long scalingFactor
= 1;
182 for (int i
= 0; i
< scaleDiff
; i
++) {
185 if (newScale
< fScale
) {
186 newValue
*= scalingFactor
;
187 newPrecision
*= scalingFactor
;
189 newValue
/= scalingFactor
;
190 newPrecision
/= scalingFactor
;
194 return new TmfTimestamp(newValue
+ offset
, newScale
, newPrecision
);
198 * Compute the adjustment, in the reference scale, needed to synchronize
199 * this timestamp with a reference timestamp.
201 * @param reference the reference timestamp to synchronize with
202 * @param scale the scale of the adjustment
203 * @return the adjustment term in the reference time scale
204 * @throws ArithmeticException
206 public long getAdjustment(TmfTimestamp reference
, byte scale
) throws ArithmeticException
{
207 TmfTimestamp ts1
= synchronize(0, scale
);
208 TmfTimestamp ts2
= reference
.synchronize(0, scale
);
209 return ts2
.fValue
- ts1
.fValue
;
213 * Compare with another timestamp
215 * @param other the other timestamp
216 * @param withinPrecision indicates if precision is to be take into consideration
217 * @return -1: this timestamp is lower (i.e. anterior)
218 * 0: timestamps are equal (within precision if requested)
219 * 1: this timestamp is higher (i.e. posterior)
221 public int compareTo(final TmfTimestamp other
, boolean withinPrecision
) {
223 // If values have the same time scale, perform the comparison
224 if (fScale
== other
.fScale
) {
225 if (withinPrecision
) {
226 if ((fValue
+ fPrecision
) < (other
.fValue
- other
.fPrecision
))
228 if ((fValue
- fPrecision
) > (other
.fValue
+ other
.fPrecision
))
232 return (fValue
== other
.fValue
) ?
0 : (fValue
< other
.fValue
) ?
-1 : 1;
235 // If values have different time scales, adjust to the finest one and
236 // then compare. If the scaling difference is too large, revert to
237 // some heuristics. Hopefully, nobody will try to compare galactic and
238 // quantic clock events...
239 if (Math
.abs(fScale
- other
.fScale
) > MAX_SCALING
) {
240 return simpleCompare(other
);
243 byte newScale
= (fScale
< other
.fScale
) ? fScale
: other
.fScale
;
245 TmfTimestamp ts1
= this.synchronize(0, newScale
);
246 TmfTimestamp ts2
= other
.synchronize(0, newScale
);
247 return ts1
.compareTo(ts2
, withinPrecision
);
248 } catch (ArithmeticException e
) {
249 return simpleCompare(other
);
253 private int simpleCompare(final TmfTimestamp other
) {
254 if ((fValue
== 0) || (other
.fValue
== 0)) {
255 return (fValue
== other
.fValue
) ?
0
256 : (fValue
< other
.fValue
) ?
-1 : 1;
258 if ((fValue
> 0) && (other
.fValue
> 0)) {
259 return (fScale
< other
.fScale
) ?
-1 : 1;
261 if ((fValue
< 0) && (other
.fValue
< 0)) {
262 return (fScale
> other
.fScale
) ?
-1 : 1;
264 return (fValue
< 0) ?
-1 : 1;
267 // ------------------------------------------------------------------------
269 // ------------------------------------------------------------------------
272 public int hashCode() {
274 result
= 37 * result
+ (int) (fValue ^
(fValue
>>> 32));
275 result
= 37 * result
+ fScale
;
276 result
= 37 * result
+ (int) (fPrecision ^
(fPrecision
>>> 32));
281 public boolean equals(Object other
) {
282 if (!(other
instanceof TmfTimestamp
))
284 TmfTimestamp o
= (TmfTimestamp
) other
;
285 return compareTo(o
, false) == 0;
289 public String
toString() {
290 return "[TmfTimestamp(" + fValue
+ "," + fScale
+ "," + fPrecision
+ ")]";
294 public TmfTimestamp
clone() {
295 TmfTimestamp clone
= null;
297 clone
= (TmfTimestamp
) super.clone();
298 clone
.fValue
= fValue
;
299 clone
.fScale
= fScale
;
300 clone
.fPrecision
= fPrecision
;
301 } catch (CloneNotSupportedException e
) {