All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cxf.common.util.AbstractTwoStageCache Maven / Gradle / Ivy

There is a newer version: 2.7.18
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cxf.common.util;

import java.lang.ref.SoftReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;


/**
 * This class pools objects, for efficiency accross a lightweight
 * fixed-size primary cache and a variable-size secondary cache - the
 * latter uses soft references to allow the polled object be GCed if
 * necessary.
 * 

* To use the cache, a subclass is defined which provides an implementation * of the abstract get() method - this may be conveniently achieved via * an anonymous subclass. The cache is then populated by calling the * populate_cache() method - the reason a two-stage process is used is * to avoid problems with the inner class create() method accessing outer * class data members from the inner class ctor (before its reference to * the outer class is initialized). *

* */ public abstract class AbstractTwoStageCache { private Object mutex; private int preallocation; private int primaryCacheSize; private int secondaryCacheHighWaterMark; private Queue primaryCache; private Queue> secondaryCache; /** * Constructor. * * @param pCacheSize primary cache size * @param secondary_cache_max secondary cache high water mark * @param preallocation the number of object to preallocation when the * cache is created */ public AbstractTwoStageCache(int pCacheSize, int highWaterMark, int prealloc) { this(pCacheSize, highWaterMark, prealloc, null); } /** * Constructor. * * @param pCacheSize primary cache size * @param secondary_cache_max secondary cache high water mark * @param preallocation the number of object to preallocation when the * cache is created * @param mutex object to use as a monitor */ public AbstractTwoStageCache(int pCacheSize, int highWaterMark, int prealloc, Object mutexParam) { this.primaryCacheSize = Math.min(pCacheSize, highWaterMark); this.secondaryCacheHighWaterMark = highWaterMark - pCacheSize; this.preallocation = prealloc > highWaterMark ? highWaterMark : prealloc; this.mutex = mutexParam != null ? mutexParam : this; } public String toString() { return "AbstractTwoStageCache"; } /** * Over-ride this method to create objects to populate the pool * * @return newly created object */ protected abstract E create() throws Exception; /** * Populate the cache */ public void populateCache() throws Exception { // create cache primaryCache = new LinkedList(); secondaryCache = new LinkedList>(); // preallocate objects into primary cache int primaryCachePreallocation = (preallocation > primaryCacheSize) ? primaryCacheSize : preallocation; for (int i = 0; i < primaryCachePreallocation; i++) { primaryCache.offer(create()); } // preallocate objects into secondary cache int secondaryCachePreallocation = preallocation - primaryCachePreallocation; for (int i = 0; i < secondaryCachePreallocation; i++) { secondaryCache.offer(new SoftReference(create())); } } /** * Return a cached or newly created object * * @return an object */ public E get() throws Exception { E ret = poll(); if (ret == null) { ret = create(); } return ret; } /** * Return a cached object if one is available * * @return an object */ public E poll() { E ret = null; synchronized (mutex) { if (primaryCache != null) { ret = primaryCache.poll(); if (ret == null) { SoftReference sr = secondaryCache.poll(); while (ret == null && sr != null) { if (sr != null) { ret = sr.get(); } if (ret == null) { sr = secondaryCache.poll(); } } } } } return ret; } /** * Recycle an old Object. * * @param oldObject the object to recycle * @return true iff the object can be accomodated in the cache */ public boolean recycle(E oldObject) { boolean cached = false; synchronized (mutex) { if (primaryCache != null) { if (primaryCache.size() < primaryCacheSize) { cached = primaryCache.offer(oldObject); } if (!cached && (secondaryCache.size() >= secondaryCacheHighWaterMark)) { // check for nulls in secondary cache and remove them to create room Iterator> it = secondaryCache.iterator(); while (it.hasNext()) { SoftReference sr = it.next(); if (sr.get() == null) { it.remove(); } } } if (!cached && (secondaryCache.size() < secondaryCacheHighWaterMark)) { cached = secondaryCache.offer(new SoftReference(oldObject)); } } } return cached; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy