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 put(key, value, DEFAULT_TIME_TO_LIVE);
083 }
084
085 @Override
086 public void put(K key, V value, int timeToLive) {
087 portalCache.put(key, value, timeToLive);
088
089 CompeteLatch competeLatch = _competeLatch.get();
090
091 if (competeLatch != null) {
092 competeLatch.done();
093
094 _competeLatch.set(null);
095 }
096
097 _competeLatchMap.remove(key);
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 private static final ThreadLocal<CompeteLatch> _competeLatch =
118 new ThreadLocal<>();
119
120 private final ConcurrentMap<K, CompeteLatch> _competeLatchMap =
121 new ConcurrentHashMap<>();
122
123 }