/** * Indicate to the cache that the client is done using the cached value for the given key. Clients * of {@link ReferenceCountedCache} must call this after finishing using the value retrieved from * the cache. The retrieved is no longer guaraunteed to be valid after it is released back to the * {@link ReferenceCountedCache} * * @param key to cache entry no longer being used by the client. * @throws java.io.IOException if closing the cached value throws an {@code IOException}. */ public void release(final K key) throws IOException { Preconditions.checkState(mIsOpen, "ReferenceCountedCache is closed."); Preconditions.checkNotNull(key); CacheEntry<V> entry = mMap.get(key); Preconditions.checkState(entry != null, "No cached value for key '%s'.", key); synchronized (entry) { if (entry.decrementAndGetCount() == 0) { // We need to remove the entry from the cache and clean up the value. mMap.remove(key); final V value = entry.getValue(); if (mTracking) { ResourceTracker.get().unregisterResource(value); } value.close(); } } }
if (entry.getCount() > 0) { entry.incrementAndGetCount(); return entry.getValue(); final CacheEntry<V> newEntry = new CacheEntry<>(); synchronized (newEntry) { newEntry.setValue(value); newEntry.incrementAndGetCount(); if (mTracking) { ResourceTracker.get().registerResource(value);
/** * Make a best effort at closing all the cached values. This method is *not* guaranteed to close * every cached value if there are concurrent users of the cache. As a result, this method * should only be relied upon if only a single thread is using this cache while {@code #close} is * called. * * @throws IOException if any entry throws an IOException while closing. An entry throwing an * IOException will prevent any further entries from being close. */ @Override public void close() throws IOException { mIsOpen = false; for (Map.Entry<K, CacheEntry<V>> entry : mMap.entrySet()) { // Attempt to remove the entry from the cache if (mMap.remove(entry.getKey(), entry.getValue())) { // If successful, close the value CacheEntry<V> cacheEntry = entry.getValue(); synchronized (cacheEntry) { final V value = cacheEntry.getValue(); if (mTracking) { ResourceTracker.get().unregisterResource(value); } cacheEntry.getValue().close(); } } } }