001
014
015 package com.liferay.portal.kernel.memory;
016
017 import java.lang.ref.ReferenceQueue;
018 import java.lang.ref.SoftReference;
019
020 import java.util.Queue;
021 import java.util.concurrent.ConcurrentLinkedQueue;
022 import java.util.concurrent.atomic.AtomicInteger;
023
024
027 public class SoftReferencePool<V, P> {
028
029 public static final int DEFAULT_IDLE_SIZE = 8;
030
031 public SoftReferencePool(PoolAction<V, P> poolAction) {
032 this(poolAction, DEFAULT_IDLE_SIZE);
033 }
034
035 public SoftReferencePool(PoolAction<V, P> poolAction, int maxIdleSize) {
036 this(poolAction, maxIdleSize, true);
037 }
038
039 public SoftReferencePool(
040 PoolAction<V, P> poolAction, int maxIdleSize, boolean useWeakCounter) {
041
042 _poolAction = poolAction;
043 _maxIdleSize = maxIdleSize;
044 _useWeakCounter = useWeakCounter;
045
046 if (_useWeakCounter) {
047 _weakCounter = new AtomicInteger();
048 }
049 else {
050 _weakCounter = null;
051 }
052 }
053
054 public V borrowObject(P parameter) {
055 while (true) {
056 SoftReference<? extends V> softReference = _softReferences.poll();
057
058 if (softReference == null) {
059 return _poolAction.onCreate(parameter);
060 }
061 else if (_useWeakCounter) {
062 _weakCounter.getAndDecrement();
063 }
064
065 V value = softReference.get();
066
067 if (value != null) {
068 return _poolAction.onBorrow(value, parameter);
069 }
070 }
071 }
072
073 public void returnObject(V value) {
074 if (_getCount() < _maxIdleSize) {
075 SoftReference<V> softReference = new SoftReference<>(
076 value, _referenceQueue);
077
078 _poolAction.onReturn(value);
079
080 _softReferences.offer(softReference);
081
082 if (_useWeakCounter) {
083 _weakCounter.getAndIncrement();
084 }
085 }
086 else {
087 while (_getCount() > _maxIdleSize) {
088 if ((_softReferences.poll() != null) && _useWeakCounter) {
089 _weakCounter.getAndDecrement();
090 }
091 }
092 }
093
094 SoftReference<? extends V> softReference = null;
095
096 while (true) {
097 softReference = (SoftReference<? extends V>)_referenceQueue.poll();
098
099 if (softReference == null) {
100 break;
101 }
102
103 if (_softReferences.remove(softReference) && _useWeakCounter) {
104 _weakCounter.getAndDecrement();
105 }
106 }
107 }
108
109 private int _getCount() {
110 if (_useWeakCounter) {
111 return _weakCounter.get();
112 }
113 else {
114 return _softReferences.size();
115 }
116 }
117
118 private final int _maxIdleSize;
119 private final PoolAction<V, P> _poolAction;
120 private final ReferenceQueue<V> _referenceQueue = new ReferenceQueue<>();
121 private final Queue<SoftReference<? extends V>> _softReferences =
122 new ConcurrentLinkedQueue<>();
123 private final boolean _useWeakCounter;
124 private final AtomicInteger _weakCounter;
125
126 }