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

pocketknife.internal.Memoizer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 pocketknife.internal;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * An abstract supertype that provides
 * memoization for idempotent operations that
 * may be computed more than once, but for which performance is prohibitive. Subclasses
 * implement the {@link #create} method with the operation to be memoized, while callers invoke the
 * {@link #get} method to utilize the memoization.
 *
 * 

Synchronization on this class is implemented using a {@link java.util.concurrent.locks.ReadWriteLock}. Multiple threads * may accessed previously memoized results without contention. * *

This class is implemented such that concurrent requests for the same key may result in * simultaneous computation in multiple threads - the instance of the result that is persisted for * subsequent invocations in not guaranteed. * *

Warning: there is no eviction. Large input sets will result in growth without bound. */ public abstract class Memoizer { private final Map map; private final Lock readLock; private final Lock writeLock; protected Memoizer() { // Don't use LinkedHashMap. This is a performance-oriented class and we don't want overhead this.map = new HashMap(); ReadWriteLock lock = new ReentrantReadWriteLock(); this.readLock = lock.readLock(); this.writeLock = lock.writeLock(); } public final V get(K key) { if (key == null) { throw new NullPointerException("key == null"); } // check to see if we already have a value readLock.lock(); try { V value = map.get(key); if (value != null) { return value; } } finally { readLock.unlock(); } // create a new value. this may race and we might create more than one instance, but that's ok V newValue = create(key); if (newValue == null) { throw new NullPointerException("create returned null"); } // write the new value and return it writeLock.lock(); try { map.put(key, newValue); return newValue; } finally { writeLock.unlock(); } } protected abstract V create(K key); @Override public final String toString() { readLock.lock(); try { return map.toString(); } finally { readLock.unlock(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy