001
014
015 package com.liferay.portal.kernel.cache;
016
017 import com.liferay.portal.kernel.concurrent.CompeteLatch;
018
019 import java.io.Serializable;
020
021 import java.util.concurrent.ConcurrentHashMap;
022 import java.util.concurrent.ConcurrentMap;
023
024
027 public class BlockingPortalCache<K extends Serializable, V>
028 extends PortalCacheWrapper<K, V> {
029
030 public BlockingPortalCache(PortalCache<K, V> portalCache) {
031 super(portalCache);
032 }
033
034 @Override
035 public V get(K key) {
036 V value = portalCache.get(key);
037
038 if (value != null) {
039 return value;
040 }
041
042 CompeteLatch lastCompeteLatch = _competeLatch.get();
043
044 if (lastCompeteLatch != null) {
045 lastCompeteLatch.done();
046
047 _competeLatch.set(null);
048 }
049
050 CompeteLatch currentCompeteLatch = _competeLatchMap.get(key);
051
052 if (currentCompeteLatch == null) {
053 CompeteLatch newCompeteLatch = new CompeteLatch();
054
055 currentCompeteLatch = _competeLatchMap.putIfAbsent(
056 key, newCompeteLatch);
057
058 if (currentCompeteLatch == null) {
059 currentCompeteLatch = newCompeteLatch;
060 }
061 }
062
063 _competeLatch.set(currentCompeteLatch);
064
065 if (!currentCompeteLatch.compete()) {
066 try {
067 currentCompeteLatch.await();
068 }
069 catch (InterruptedException ie) {
070 }
071
072 _competeLatch.set(null);
073
074 value = portalCache.get(key);
075 }
076
077 return value;
078 }
079
080 @Override
081 public void put(K key, V value) {
082 doPut(key, value, DEFAULT_TIME_TO_LIVE, false);
083 }
084
085 @Override
086 public void put(K key, V value, int timeToLive) {
087 doPut(key, value, timeToLive, false);
088 }
089
090 @Override
091 public void putQuiet(K key, V value) {
092 doPut(key, value, DEFAULT_TIME_TO_LIVE, true);
093 }
094
095 @Override
096 public void putQuiet(K key, V value, int timeToLive) {
097 doPut(key, value, timeToLive, true);
098 }
099
100 @Override
101 public void remove(K key) {
102 portalCache.remove(key);
103
104 CompeteLatch competeLatch = _competeLatchMap.remove(key);
105
106 if (competeLatch != null) {
107 competeLatch.done();
108 }
109 }
110
111 @Override
112 public void removeAll() {
113 portalCache.removeAll();
114 _competeLatchMap.clear();
115 }
116
117 protected void doPut(K key, V value, int timeToLive, boolean quiet) {
118 if (quiet) {
119 portalCache.putQuiet(key, value, timeToLive);
120 }
121 else {
122 portalCache.put(key, value, timeToLive);
123 }
124
125 CompeteLatch competeLatch = _competeLatch.get();
126
127 if (competeLatch != null) {
128 competeLatch.done();
129
130 _competeLatch.set(null);
131 }
132
133 _competeLatchMap.remove(key);
134 }
135
136 private static final ThreadLocal<CompeteLatch> _competeLatch =
137 new ThreadLocal<CompeteLatch>();
138
139 private final ConcurrentMap<K, CompeteLatch> _competeLatchMap =
140 new ConcurrentHashMap<K, CompeteLatch>();
141
142 }