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

com.cinchapi.concourse.cache.ReferenceCache Maven / Gradle / Ivy

/*
 * Copyright (c) 2013-2017 Cinchapi Inc.
 *
 * Licensed 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 com.cinchapi.concourse.cache;

import javax.annotation.Nullable;

import com.google.common.base.Preconditions;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;

/**
 * 

* A concurrent cache that holds references to objects so as to prevent * unnecessary constructor calls. The cache does not have a maximum capacity or * expulsion policy, but it uses a SoftReference for each stored object so that * the garbage collector will clear the cache only before an OOM occurs. *

*

Example:

* *
 *  private class Foo {
 *    
 *    int id;
 *    String label;
 *    Bar bar;
 *    
 *    private static final ReferenceCache{@literal } cache = new ReferenceCache{@literal }();
 *    
 *    public static Foo newInstance(int id, String label, Bar bar){
 *    	Foo foo = cache.get(id, label, bar); // use the combination of id, label and bar as a cacheKey
 *    	if(foo == null){
 *    	    foo = new Foo(id, label, bar);
 *    		cache.put(foo, id, label, bar);
 *    	}
 *    	return foo;
 *    }
 *    
 *    private Foo(int id, String label, Bar bar){
 *    	this.id = id;
 *    	this.label = label;
 *    	this.bar = bar;
 *    }
 * }
 * 
* * @author Jeff Nelson * @param - the cached object type. */ public class ReferenceCache { private static final int INITIAL_CAPACITY = 500000; private static final int CONCURRENCY_LEVEL = 16; private final Cache cache = CacheBuilder.newBuilder() .initialCapacity(INITIAL_CAPACITY) .concurrencyLevel(CONCURRENCY_LEVEL).softValues().build(); /** * Return the cache value associated with the group of {@code args} or * {@code null} if not value is found. * * @param args * @return the cached value. */ @Nullable public T get(Object... args) { HashCode id = getCacheKey(args); return cache.getIfPresent(id); } /** * Cache {@code value} and associated it with the group of {@code args}. * Each arg should be a value that is used to construct * the object. * * @param value * @param args */ public void put(T value, Object... args) { Preconditions.checkNotNull(value); Preconditions.checkNotNull(args); Preconditions.checkArgument(args.length > 0, "You must specify at least one key"); HashCode id = getCacheKey(args); cache.put(id, value); } /** * Remove the value associated with the group of {@code args} from the * cache. * * @param args */ public void remove(Object... args) { cache.invalidate(getCacheKey(args)); } /** * Return a unique identifier for a group of {@code args}. * * @param args * @return the identifier. */ private HashCode getCacheKey(Object... args) { StringBuilder key = new StringBuilder(); for (Object o : args) { key.append(o.hashCode()); key.append(o.getClass().getName()); } return Hashing.md5().hashUnencodedChars(key.toString()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy