1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.spf4j.reflect;
33
34 import com.google.common.cache.CacheBuilder;
35 import com.google.common.cache.CacheLoader;
36 import com.google.common.cache.LoadingCache;
37 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
38 import java.lang.reflect.Type;
39 import java.util.Set;
40 import java.util.function.Function;
41 import javax.annotation.concurrent.GuardedBy;
42 import javax.annotation.concurrent.ThreadSafe;
43 import org.spf4j.concurrent.UnboundedLoadingCache;
44
45
46
47
48 @ThreadSafe
49 public final class CachingTypeMapWrapper<H> implements TypeMap<H> {
50
51 private final LoadingCache<Type, Set<H>> cache;
52
53 @GuardedBy("syncObj")
54 private final TypeMap<H> wrapped;
55
56 private final Object syncObj;
57
58 @SuppressFBWarnings("EI_EXPOSE_REP2")
59 public CachingTypeMapWrapper(final CacheBuilder<Type, Set<H>> cacheBuilder, final TypeMap wrapped) {
60 this.syncObj = new Object();
61 this.wrapped = wrapped;
62 cache = cacheBuilder.build(new TypeMapedObjLoader());
63 }
64
65 @SuppressFBWarnings("EI_EXPOSE_REP2")
66 public CachingTypeMapWrapper(final TypeMap wrapped) {
67 this.syncObj = new Object();
68 this.wrapped = wrapped;
69 cache = new UnboundedLoadingCache<>(16, new TypeMapedObjLoader());
70 }
71
72
73 @Override
74 public Set<H> getAll(final Type t) {
75 return cache.getUnchecked(t);
76 }
77
78 @Override
79 public boolean putIfNotPresent(final Type type, final H appender) {
80 synchronized (syncObj) {
81 return wrapped.putIfNotPresent(type, appender);
82 }
83 }
84
85 @Override
86 public boolean remove(final Type type) {
87 boolean remove;
88 synchronized (syncObj) {
89 remove = wrapped.remove(type);
90 }
91 if (remove) {
92 cache.invalidateAll();
93 return true;
94 } else {
95 return false;
96 }
97 }
98
99 @Override
100 public H getExact(final Type t) {
101 synchronized (wrapped) {
102 return wrapped.getExact(t);
103 }
104 }
105
106 public void replace(final Type t, final Function<H, H> f) {
107 synchronized (wrapped) {
108 H exact = wrapped.getExact(t);
109 if (exact != null && !wrapped.remove(t)) {
110 throw new IllegalStateException("Illegal Stat, type = " + t + " wrapped = " + wrapped);
111 }
112 wrapped.safePut(t, f.apply(exact));
113 }
114 cache.invalidateAll();
115 }
116
117 public void clearCache() {
118 cache.invalidateAll();
119 }
120
121 private final class TypeMapedObjLoader extends CacheLoader<Type, Set<H>> {
122
123 @Override
124 public Set<H> load(final Type key) throws Exception {
125 synchronized (wrapped) {
126 return wrapped.getAll(key);
127 }
128 }
129 }
130
131 @Override
132 public String toString() {
133 String wts;
134 synchronized (wrapped) {
135 wts = wrapped.toString();
136 }
137 return "CachingTypeMapWrapper{" + "cache=" + cache + ", wrapped=" + wts + '}';
138 }
139
140
141 }