001: /* MultiCache.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Wed Aug 29 17:29:45 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.util;
020:
021: import org.zkoss.lang.Objects;
022:
023: /**
024: * A {@link CacheMap}-based cache.
025: * It creates multiple instances of {@link CacheMap}, called
026: * the internal caches, and then distributes the access across them.
027: * Thus, the performance is porportional to the number of internal caches.
028: *
029: * <p>Thread safe.
030: *
031: * @author tomyeh
032: * @since 3.0.0
033: */
034: public class MultiCache implements Cache, java.io.Serializable,
035: Cloneable {
036: private final CacheMap[] _caches;
037: private int _maxsize;
038:
039: /** Constructs a multi cache with 16 inital caches.
040: */
041: public MultiCache() {
042: this (16);
043: }
044:
045: /** Constucts a multi cache with the specified number of internal caches,
046: * the max size and the lifetime.
047: *
048: * @param nCache the postive number of the internal caches.
049: * The large the number the fast the performance.
050: */
051: public MultiCache(int nCache, int maxSize, int lifetime) {
052: this (nCache);
053: setMaxSize(maxSize);
054: setLifetime(lifetime);
055: }
056:
057: /** Constructs a multi cache with the specified number of internal caches.
058: *
059: * @param nCache the postive number of the internal caches.
060: * The large the number the fast the performance.
061: */
062: public MultiCache(int nCache) {
063: if (nCache <= 0)
064: throw new IllegalArgumentException("Positive only");
065:
066: _caches = new CacheMap[nCache];
067: for (int j = 0; j < nCache; ++j) {
068: _caches[j] = new CacheMap(8);
069: _maxsize += _caches[j].getMaxSize();
070: }
071: }
072:
073: /* Used by {@link #clone} only. */
074: private MultiCache(CacheMap[] clone, int maxsize) {
075: _maxsize = maxsize;
076: _caches = new CacheMap[clone.length];
077: for (int j = 0; j < clone.length; ++j)
078: _caches[j] = (CacheMap) clone[j].clone();
079: }
080:
081: /** Constructs a multi cache with the specified number of internal caches
082: * and the initialize size.
083: *
084: * @param nCache the postive number of the internal caches.
085: * The large the number the fast the performance.
086: * @param initSize the initialize size
087: */
088: public MultiCache(int nCache, int initSize) {
089: if (nCache <= 0 || initSize <= 0)
090: throw new IllegalArgumentException("Positive only");
091:
092: initSize = (initSize - 1) / nCache + 1;
093: _caches = new CacheMap[nCache];
094: for (int j = 0; j < nCache; ++j) {
095: _caches[j] = new CacheMap(initSize);
096: _maxsize += _caches[j].getMaxSize();
097: }
098: }
099:
100: //Cache//
101: public boolean containsKey(Object key) {
102: final CacheMap map = getCache(key);
103: synchronized (map) {
104: return map.containsKey(key);
105: }
106: }
107:
108: public Object get(Object key) {
109: final CacheMap map = getCache(key);
110: synchronized (map) {
111: return map.get(key);
112: }
113: }
114:
115: public Object put(Object key, Object value) {
116: final CacheMap map = getCache(key);
117: synchronized (map) {
118: return map.put(key, value);
119: }
120: }
121:
122: public Object remove(Object key) {
123: final CacheMap map = getCache(key);
124: synchronized (map) {
125: return map.remove(key);
126: }
127: }
128:
129: public void clear() {
130: for (int j = 0; j < _caches.length; ++j) {
131: synchronized (_caches[j]) {
132: _caches[j].clear();
133: }
134: }
135: }
136:
137: private CacheMap getCache(Object key) {
138: int hc = Objects.hashCode(key);
139: hc = (hc >>> 13) ^ hc;
140: if (hc < 0)
141: hc = -hc;
142: return _caches[hc % _caches.length];
143: }
144:
145: public int getLifetime() {
146: return _caches[0].getLifetime();
147: }
148:
149: public void setLifetime(int lifetime) {
150: synchronized (this ) {
151: for (int j = 0; j < _caches.length; ++j)
152: _caches[j].setLifetime(lifetime);
153: }
154: }
155:
156: public int getMaxSize() {
157: return _maxsize;
158: }
159:
160: public void setMaxSize(int maxsize) {
161: _maxsize = maxsize;
162:
163: int v = maxsize / _caches.length;
164: if (v == 0)
165: v = maxsize > 0 ? 1 : maxsize < 0 ? -1 : 0;
166:
167: synchronized (this ) {
168: for (int j = 0; j < _caches.length; ++j)
169: _caches[j].setMaxSize(v);
170: }
171: }
172:
173: //Cloneable//
174: public Object clone() {
175: return new MultiCache(_caches, _maxsize);
176: }
177: }
|