1
2
3
4
5 package oshi.util;
6
7 import java.util.concurrent.TimeUnit;
8 import java.util.function.Supplier;
9
10 import oshi.annotation.concurrent.ThreadSafe;
11
12
13
14
15
16 @ThreadSafe
17 public final class Memoizer {
18
19 private static final Supplier<Long> DEFAULT_EXPIRATION_NANOS = memoize(Memoizer::queryExpirationConfig,
20 TimeUnit.MINUTES.toNanos(1));
21
22 private Memoizer() {
23 }
24
25 private static long queryExpirationConfig() {
26 return TimeUnit.MILLISECONDS.toNanos(GlobalConfig.get(GlobalConfig.OSHI_UTIL_MEMOIZER_EXPIRATION, 300));
27 }
28
29
30
31
32
33
34
35 public static long defaultExpiration() {
36 return DEFAULT_EXPIRATION_NANOS.get();
37 }
38
39
40
41
42
43
44
45
46
47 public static <T> Supplier<T> memoize(Supplier<T> original, long ttlNanos) {
48
49 return new Supplier<T>() {
50 private final Supplier<T> delegate = original;
51 private volatile T value;
52 private volatile long expirationNanos;
53
54 @Override
55 public T get() {
56 long nanos = expirationNanos;
57 long now = System.nanoTime();
58 if (nanos == 0 || (ttlNanos >= 0 && now - nanos >= 0)) {
59 synchronized (this) {
60 if (nanos == expirationNanos) {
61 T t = delegate.get();
62 value = t;
63 nanos = now + ttlNanos;
64 expirationNanos = (nanos == 0) ? 1 : nanos;
65 return t;
66 }
67 }
68 }
69 return value;
70 }
71 };
72 }
73
74
75
76
77
78
79
80
81 public static <T> Supplier<T> memoize(Supplier<T> original) {
82 return memoize(original, -1L);
83 }
84 }