1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.spf4j.base;
17
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import java.util.function.LongSupplier;
21
22
23
24
25
26 public final class TimeSource {
27
28 private static final LongSupplier TIMESUPP;
29
30 static {
31 String cfgTimeSource = System.getProperty("spf4j.timeSource");
32 if (cfgTimeSource == null) {
33 TIMESUPP = () -> System.nanoTime();
34 } else if ("systemTime".equals(cfgTimeSource)) {
35
36
37
38
39
40 TIMESUPP = new SystemTimeProvider();
41 } else {
42 try {
43 TIMESUPP = (LongSupplier) Class.forName(cfgTimeSource).newInstance();
44 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
45 throw new ExceptionInInitializerError(ex);
46 }
47 }
48
49 }
50
51 private TimeSource() { }
52
53
54
55
56
57
58 public static long nanoTime() {
59 return TIMESUPP.getAsLong();
60 }
61
62 public static LongSupplier nanoTimeSupplier() {
63 return TIMESUPP;
64 }
65
66 public static long getDeadlineNanos(final long timeout, final TimeUnit timeUnit) {
67 if (timeout < 0) {
68 throw new IllegalArgumentException("Invalid timeout " + timeout + " " + timeUnit);
69 }
70 return nanoTime() + timeUnit.toNanos(timeout);
71 }
72
73 public static long getDeadlineNanos(final long currentTimeNanos, final long timeout, final TimeUnit timeUnit) {
74 if (timeout < 0) {
75 throw new IllegalArgumentException("Invalid timeout " + timeout + " " + timeUnit);
76 }
77 return currentTimeNanos + timeUnit.toNanos(timeout);
78 }
79
80
81 public static long getTimeToDeadlineStrict(final long deadlineNanos, final TimeUnit timeUnit)
82 throws TimeoutException {
83 long timeoutNanos = deadlineNanos - nanoTime();
84 if (timeoutNanos < 0) {
85 throw new TimeoutException("Exceeded deadline " + deadlineNanos + " with " + (-timeoutNanos));
86 }
87 return timeUnit.convert(timeoutNanos, TimeUnit.NANOSECONDS);
88 }
89
90 public static long getTimeToDeadline(final long deadlineNanos, final TimeUnit timeUnit) {
91 long timeoutNanos = deadlineNanos - nanoTime();
92 return timeUnit.convert(timeoutNanos, TimeUnit.NANOSECONDS);
93 }
94
95 private static final class SystemTimeProvider implements LongSupplier {
96
97 private static final long LOCAL_EPOCH = System.currentTimeMillis();
98
99 @Override
100 public long getAsLong() {
101 return TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis() - LOCAL_EPOCH);
102 }
103
104 }
105
106
107 }