/** Drains the weak / soft value references queue. */ @GuardedBy("evictionLock") void drainValueReferences() { if (!collectValues()) { return; } Reference<? extends V> valueRef; while ((valueRef = valueReferenceQueue().poll()) != null) { @SuppressWarnings("unchecked") InternalReference<V> ref = (InternalReference<V>) valueRef; Node<K, V> node = data.get(ref.getKeyReference()); if ((node != null) && (valueRef == node.getValueReference())) { evictEntry(node, RemovalCause.COLLECTED, 0L); } } }
/** Creates an instance based on the builder's configuration. */ protected BoundedLocalCache(Caffeine<K, V> builder, @Nullable CacheLoader<K, V> cacheLoader, boolean isAsync) { this.isAsync = isAsync; this.cacheLoader = cacheLoader; executor = builder.getExecutor(); writer = builder.getCacheWriter(); evictionLock = new ReentrantLock(); weigher = builder.getWeigher(isAsync); drainBuffersTask = new PerformCleanupTask(); nodeFactory = NodeFactory.newFactory(builder, isAsync); data = new ConcurrentHashMap<>(builder.getInitialCapacity()); readBuffer = evicts() || collectKeys() || collectValues() || expiresAfterAccess() ? new BoundedBuffer<>() : Buffer.disabled(); accessPolicy = (evicts() || expiresAfterAccess()) ? this::onAccess : e -> {}; if (evicts()) { setMaximum(builder.getMaximum()); } }
if (!cache.collectValues()) { desc.expectThat("not null value", value, is(not(nullValue()))); if ((key != null) && !cache.hasExpired(node, cache.expirationTicker().read())) {
@Override public @Nullable V getIfPresent(Object key, boolean recordStats) { Node<K, V> node = data.get(nodeFactory.newLookupKey(key)); if (node == null) { if (recordStats) { statsCounter().recordMisses(1); } return null; } V value = node.getValue(); long now = expirationTicker().read(); if (hasExpired(node, now) || (collectValues() && (value == null))) { if (recordStats) { statsCounter().recordMisses(1); } scheduleDrainBuffers(); return null; } if (!isComputingAsync(node)) { @SuppressWarnings("unchecked") K castedKey = (K) key; setAccessTime(node, now); setVariableTime(node, expireAfterRead(node, castedKey, value, expiry(), now)); } afterRead(node, now, recordStats); return value; }
/** Drains the weak / soft value references queue. */ @GuardedBy("evictionLock") void drainValueReferences() { if (!collectValues()) { return; } Reference<? extends V> valueRef; while ((valueRef = valueReferenceQueue().poll()) != null) { @SuppressWarnings("unchecked") InternalReference<V> ref = (InternalReference<V>) valueRef; Node<K, V> node = data.get(ref.getKeyReference()); if ((node != null) && (valueRef == node.getValueReference())) { evictEntry(node, RemovalCause.COLLECTED, 0L); } } }
/** Creates an instance based on the builder's configuration. */ protected BoundedLocalCache(Caffeine<K, V> builder, @Nullable CacheLoader<K, V> cacheLoader, boolean isAsync) { this.isAsync = isAsync; this.cacheLoader = cacheLoader; executor = builder.getExecutor(); writer = builder.getCacheWriter(); evictionLock = new ReentrantLock(); weigher = builder.getWeigher(isAsync); drainBuffersTask = new PerformCleanupTask(); nodeFactory = NodeFactory.newFactory(builder, isAsync); data = new ConcurrentHashMap<>(builder.getInitialCapacity()); readBuffer = evicts() || collectKeys() || collectValues() || expiresAfterAccess() ? new BoundedBuffer<>() : Buffer.disabled(); accessPolicy = (evicts() || expiresAfterAccess()) ? this::onAccess : e -> {}; if (evicts()) { setMaximum(builder.getMaximum()); } }