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 }
050
051 public V borrowObject(P parameter) {
052 while (true) {
053 SoftReference<? extends V> softReference = _softReferences.poll();
054
055 if (softReference == null) {
056 return _poolAction.onCreate(parameter);
057 }
058 else if (_useWeakCounter) {
059 _weakCounter.getAndDecrement();
060 }
061
062 V value = softReference.get();
063
064 if (value != null) {
065 return _poolAction.onBorrow(value, parameter);
066 }
067 }
068 }
069
070 public void returnObject(V value) {
071 if (_getCount() < _maxIdleSize) {
072 SoftReference<V> softReference = new SoftReference<V>(
073 value, _referenceQueue);
074
075 _poolAction.onReturn(value);
076
077 _softReferences.offer(softReference);
078
079 if (_useWeakCounter) {
080 _weakCounter.getAndIncrement();
081 }
082 }
083 else {
084 while (_getCount() > _maxIdleSize) {
085 if ((_softReferences.poll() != null) && _useWeakCounter) {
086 _weakCounter.getAndDecrement();
087 }
088 }
089 }
090
091 SoftReference<? extends V> softReference = null;
092
093 while (true) {
094 softReference = (SoftReference<? extends V>)_referenceQueue.poll();
095
096 if (softReference == null) {
097 break;
098 }
099
100 if (_softReferences.remove(softReference) && _useWeakCounter) {
101 _weakCounter.getAndDecrement();
102 }
103 }
104 }
105
106 private int _getCount() {
107 if (_useWeakCounter) {
108 return _weakCounter.get();
109 }
110 else {
111 return _softReferences.size();
112 }
113 }
114
115 private int _maxIdleSize;
116 private PoolAction<V, P> _poolAction;
117 private ReferenceQueue<V> _referenceQueue = new ReferenceQueue<V>();
118 private Queue<SoftReference<? extends V>> _softReferences =
119 new ConcurrentLinkedQueue<SoftReference<? extends V>>();
120 private boolean _useWeakCounter;
121 private AtomicInteger _weakCounter;
122
123 }