View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.terracotta;
18  
19  import java.lang.ref.Reference;
20  import java.lang.ref.ReferenceQueue;
21  import java.lang.ref.WeakReference;
22  import java.util.HashSet;
23  import java.util.Set;
24  import java.util.concurrent.ConcurrentHashMap;
25  import java.util.concurrent.ConcurrentMap;
26  
27  /***
28   * A poor man's implementation of a WeakIdentityConcurrentMap to hold the CacheManager associated ExecutorServices
29   * @param <K> The key type
30   * @param <V> The value type
31   * @author Alex Snaps
32   */
33  final class WeakIdentityConcurrentMap<K, V> {
34  
35      private ConcurrentMap<WeakReference<K>, V> map = new ConcurrentHashMap<WeakReference<K>, V>();
36      private ReferenceQueue<K> queue = new ReferenceQueue<K>();
37  
38      private final CleanUpTask<V> cleanUpTask;
39  
40      /***
41       * Constructor
42       * @param cleanUpTask
43       */
44      WeakIdentityConcurrentMap(final CleanUpTask<V> cleanUpTask) {
45          this.cleanUpTask = cleanUpTask;
46      }
47  
48      /***
49       * Puts into the underlying
50       * @param key
51       * @param value
52       * @return
53       */
54      V putIfAbsent(K key, V value) {
55          cleanUp();
56          return map.putIfAbsent(new IdentityWeakReference<K>(key, queue), value);
57      }
58  
59      /***
60       * @param key
61       * @return
62       */
63      V get(K key) {
64          cleanUp();
65          return map.get(new IdentityWeakReference<K>(key));
66      }
67  
68      /***
69       *
70       */
71      void cleanUp() {
72  
73          Reference<? extends K> reference;
74          while ((reference = queue.poll()) != null) {
75              final V value = map.remove(reference);
76              if (value != null) {
77                  cleanUpTask.cleanUp(value);
78              }
79          }
80      }
81  
82      /***
83       *
84       * @return
85       */
86      Set<K> keySet() {
87          cleanUp();
88          K k;
89          final HashSet<K> ks = new HashSet<K>();
90          for (WeakReference<K> weakReference : map.keySet()) {
91              k = weakReference.get();
92              if (k != null) {
93                  ks.add(k);
94              }
95          }
96          return ks;
97      }
98  
99      /***
100      * @param <T>
101      */
102     private static final class IdentityWeakReference<T> extends WeakReference<T> {
103 
104         private final int hashCode;
105 
106         /***
107          * @param reference
108          */
109         IdentityWeakReference(T reference) {
110             this(reference, null);
111         }
112 
113         /***
114          * @param reference
115          * @param referenceQueue
116          */
117         IdentityWeakReference(T reference, ReferenceQueue<T> referenceQueue) {
118             super(reference, referenceQueue);
119             this.hashCode = (reference == null) ? 0 : System.identityHashCode(reference);
120         }
121 
122         /***
123          * {@inheritDoc}
124          */
125         @Override
126         public boolean equals(Object o) {
127             if (this == o) {
128                 return true;
129             }
130             if (!(o instanceof IdentityWeakReference<?>)) {
131                 return false;
132             } else {
133                 IdentityWeakReference<?> wr = (IdentityWeakReference<?>)o;
134                 Object got = get();
135                 return (got != null && got == wr.get());
136             }
137         }
138 
139         /***
140          * {@inheritDoc}
141          */
142         @Override
143         public int hashCode() {
144             return hashCode;
145         }
146     }
147 
148     /***
149      * @param <T>
150      */
151     static interface CleanUpTask<T> {
152 
153         /***
154          * @param object
155          */
156         void cleanUp(T object);
157     }
158 }