2626import java .util .concurrent .TimeUnit ;
2727
2828/**
29- * MapMaker emulation. Since Javascript is single-threaded and have no
30- * references, this reduces to the creation of expiring and computing maps.
29+ * MapMaker emulation. Since Javascript is single-threaded and have no references, this reduces to
30+ * the creation of expiring and computing maps.
3131 *
3232 * @author Charles Fry
3333 */
3434public class MapMaker extends GenericMapMaker <Object , Object > {
3535
36- // TODO(user,user): ConcurrentHashMap never throws a CME when mutating the map
37- // during iteration, but this implementation (based on a LHM) does.
38- // This will all be replaced soon anyways, so leaving it as is for now.
39- private static class ExpiringComputingMap <K , V >
40- extends LinkedHashMap < K , V > implements ConcurrentMap <K , V > {
36+ // TODO(user,user): ConcurrentHashMap never throws a CME when mutating the map during iteration, but
37+ // this implementation (based on a LHM) does. This will all be replaced soon anyways, so leaving
38+ // it as is for now.
39+ private static class ExpiringComputingMap <K , V > extends LinkedHashMap < K , V >
40+ implements ConcurrentMap <K , V > {
4141 private final long expirationMillis ;
4242 private final Function <? super K , ? extends V > computer ;
4343 private final int maximumSize ;
4444
45- ExpiringComputingMap (long expirationMillis , int maximumSize ,
46- int initialCapacity , float loadFactor ) {
45+ ExpiringComputingMap (long expirationMillis , int maximumSize , int initialCapacity ,
46+ float loadFactor ) {
4747 this (expirationMillis , null , maximumSize , initialCapacity , loadFactor );
4848 }
4949
50- ExpiringComputingMap (long expirationMillis ,
51- Function <? super K , ? extends V > computer , int maximumSize ,
52- int initialCapacity , float loadFactor ) {
50+ ExpiringComputingMap (long expirationMillis , Function <? super K , ? extends V > computer ,
51+ int maximumSize , int initialCapacity , float loadFactor ) {
5352 super (initialCapacity , loadFactor , (maximumSize != -1 ));
5453 this .expirationMillis = expirationMillis ;
5554 this .computer = computer ;
@@ -105,16 +104,15 @@ public V replace(K key, V value) {
105104 private void scheduleRemoval (final K key , final V value ) {
106105 // from MapMaker
107106 /*
108- * TODO: Keep weak reference to map, too. Build a priority
109- * queue out of the entries themselves instead of creating a
110- * task per entry. Then, we could have one recurring task per
111- * map (which would clean the entire map and then reschedule
112- * itself depending upon when the next expiration comes). We
113- * also want to avoid removing an entry prematurely if the
114- * entry was set to the same value again.
107+ * TODO: Keep weak reference to map, too. Build a priority queue out of the entries themselves
108+ * instead of creating a task per entry. Then, we could have one recurring task per map (which
109+ * would clean the entire map and then reschedule itself depending upon when the next
110+ * expiration comes). We also want to avoid removing an entry prematurely if the entry was set
111+ * to the same value again.
115112 */
116113 Timer timer = new Timer () {
117- @ Override public void run () {
114+ @ Override
115+ public void run () {
118116 remove (key , value );
119117 }
120118 };
@@ -127,13 +125,13 @@ public V get(Object k) {
127125 V result = super .get (k );
128126 if (result == null && computer != null ) {
129127 /*
130- * This cast isn't safe, but we can rely on the fact that K is almost
131- * always passed to Map.get(), and tools like IDEs and Findbugs can
132- * catch situations where this isn't the case.
128+ * This cast isn't safe, but we can rely on the fact that K is almost always passed to
129+ * Map.get(), and tools like IDEs and Findbugs can catch situations where this isn't the
130+ * case.
133131 *
134- * The alternative is to add an overloaded method, but the chances of
135- * a user calling get() instead of the new API and the risks inherent
136- * in adding a new API outweigh this little hole.
132+ * The alternative is to add an overloaded method, but the chances of a user calling get()
133+ * instead of the new API and the risks inherent in adding a new API outweigh this little
134+ * hole.
137135 */
138136 @ SuppressWarnings ("unchecked" )
139137 K key = (K ) k ;
@@ -193,8 +191,8 @@ public MapMaker expiration(long duration, TimeUnit unit) {
193191 @ Override
194192 public MapMaker expireAfterWrite (long duration , TimeUnit unit ) {
195193 if (expirationMillis != 0 ) {
196- throw new IllegalStateException ("expiration time of "
197- + expirationMillis + " ns was already set" );
194+ throw new IllegalStateException (
195+ "expiration time of " + expirationMillis + " ns was already set" );
198196 }
199197 if (duration <= 0 ) {
200198 throw new IllegalArgumentException ("invalid duration: " + duration );
@@ -207,12 +205,10 @@ public MapMaker expireAfterWrite(long duration, TimeUnit unit) {
207205 @ Override
208206 public MapMaker maximumSize (int maximumSize ) {
209207 if (this .maximumSize != -1 ) {
210- throw new IllegalStateException ("maximum size of " + maximumSize
211- + " was already set" );
208+ throw new IllegalStateException ("maximum size of " + maximumSize + " was already set" );
212209 }
213210 if (maximumSize < 0 ) {
214- throw new IllegalArgumentException ("invalid maximum size: "
215- + maximumSize );
211+ throw new IllegalArgumentException ("invalid maximum size: " + maximumSize );
216212 }
217213 this .maximumSize = maximumSize ;
218214 useCustomMap = true ;
@@ -222,8 +218,7 @@ public MapMaker maximumSize(int maximumSize) {
222218 @ Override
223219 public MapMaker concurrencyLevel (int concurrencyLevel ) {
224220 if (concurrencyLevel < 1 ) {
225- throw new IllegalArgumentException (
226- "GWT only supports a concurrency level of 1" );
221+ throw new IllegalArgumentException ("GWT only supports a concurrency level of 1" );
227222 }
228223 // GWT technically only supports concurrencyLevel == 1, but we silently
229224 // ignore other positive values.
@@ -233,15 +228,14 @@ public MapMaker concurrencyLevel(int concurrencyLevel) {
233228 @ Override
234229 public <K , V > ConcurrentMap <K , V > makeMap () {
235230 return useCustomMap
236- ? new ExpiringComputingMap <K , V >(
237- expirationMillis , null , maximumSize , initialCapacity , loadFactor )
231+ ? new ExpiringComputingMap <K , V >(expirationMillis , null , maximumSize , initialCapacity ,
232+ loadFactor )
238233 : new ConcurrentHashMap <K , V >(initialCapacity , loadFactor );
239234 }
240235
241236 @ Override
242- public <K , V > ConcurrentMap <K , V > makeComputingMap (
243- Function <? super K , ? extends V > computer ) {
244- return new ExpiringComputingMap <K , V >(
245- expirationMillis , computer , maximumSize , initialCapacity , loadFactor );
237+ public <K , V > ConcurrentMap <K , V > makeComputingMap (Function <? super K , ? extends V > computer ) {
238+ return new ExpiringComputingMap <K , V >(expirationMillis , computer , maximumSize , initialCapacity ,
239+ loadFactor );
246240 }
247241}
0 commit comments