/** Records that the current thread is about to wait on the specified guard. */ @GuardedBy("lock") private void beginWaitingFor(Guard guard) { int waiters = guard.waiterCount++; if (waiters == 0) { // push guard onto activeGuards guard.next = activeGuards; activeGuards = guard; } }
/** Signals all threads waiting on guards. */ @GuardedBy("lock") private void signalAllWaiters() { for (Guard guard = activeGuards; guard != null; guard = guard.next) { guard.condition.signalAll(); } }
/** * Performs routine cleanup prior to executing a write. This should be called every time a write * thread acquires the segment lock, immediately after acquiring the lock. * * <p>Post-condition: expireEntries has been run. */ @GuardedBy("this") void preWriteCleanup(long now) { runLockedCleanup(now); }
/** * Performs routine cleanup prior to executing a write. This should be called every time a write * thread acquires the segment lock, immediately after acquiring the lock. */ @GuardedBy("this") void preWriteCleanup() { runLockedCleanup(); }
@GuardedBy("this") void drainValueReferenceQueue() { Reference<? extends V> ref; int i = 0; while ((ref = valueReferenceQueue.poll()) != null) { @SuppressWarnings("unchecked") ValueReference<K, V> valueReference = (ValueReference<K, V>) ref; map.reclaimValue(valueReference); if (++i == DRAIN_MAX) { break; } } }
@GuardedBy("this") void drainKeyReferenceQueue(ReferenceQueue<K> keyReferenceQueue) { Reference<? extends K> ref; int i = 0; while ((ref = keyReferenceQueue.poll()) != null) { @SuppressWarnings("unchecked") E entry = (E) ref; map.reclaimKey(entry); if (++i == DRAIN_MAX) { break; } } }
@GuardedBy("this") void drainKeyReferenceQueue() { Reference<? extends K> ref; int i = 0; while ((ref = keyReferenceQueue.poll()) != null) { @SuppressWarnings("unchecked") ReferenceEntry<K, V> entry = (ReferenceEntry<K, V>) ref; map.reclaimKey(entry); if (++i == DRAIN_MAX) { break; } } }
@GuardedBy("this") void drainValueReferenceQueue(ReferenceQueue<V> valueReferenceQueue) { Reference<? extends V> ref; int i = 0; while ((ref = valueReferenceQueue.poll()) != null) { @SuppressWarnings("unchecked") WeakValueReference<K, V, E> valueReference = (WeakValueReference<K, V, E>) ref; map.reclaimValue(valueReference); if (++i == DRAIN_MAX) { break; } } }
@GuardedBy("this") ReferenceEntry<K, V> getNextEvictable() { for (ReferenceEntry<K, V> e : accessQueue) { int weight = e.getValueReference().getWeight(); if (weight > 0) { return e; } } throw new AssertionError(); }
@GuardedBy("this") ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) { return map.entryFactory.newEntry(this, checkNotNull(key), hash, next); }
/** * Updates the eviction metadata that {@code entry} was just read. This currently amounts to * adding {@code entry} to relevant eviction lists. * * <p>Note: this method should only be called under lock, as it directly manipulates the * eviction queues. Unlocked reads should use {@link #recordRead}. */ @GuardedBy("this") void recordLockedRead(ReferenceEntry<K, V> entry, long now) { if (map.recordsAccess()) { entry.setAccessTime(now); } accessQueue.add(entry); }
@Override @GuardedBy("ServiceManagerState.this.monitor") public boolean isSatisfied() { return states.count(TERMINATED) + states.count(FAILED) == numberOfServices; } }
/** * Exactly like guard.isSatisfied(), but in addition signals all waiting threads in the (hopefully * unlikely) event that isSatisfied() throws. */ @GuardedBy("lock") private boolean isSatisfied(Guard guard) { try { return guard.isSatisfied(); } catch (Throwable throwable) { signalAllWaiters(); throw throwable; } }
@GuardedBy("lock") private void await(Guard guard, boolean signalBeforeWaiting) throws InterruptedException { if (signalBeforeWaiting) { signalNextWaiter(); } beginWaitingFor(guard); try { do { guard.condition.await(); } while (!guard.isSatisfied()); } finally { endWaitingFor(guard); } }
@GuardedBy("this") void enqueueNotification( @Nullable K key, int hash, @Nullable V value, int weight, RemovalCause cause) { totalWeight -= weight; if (cause.wasEvicted()) { statsCounter.recordEviction(); } if (map.removalNotificationQueue != DISCARDING_QUEUE) { RemovalNotification<K, V> notification = RemovalNotification.create(key, value, cause); map.removalNotificationQueue.offer(notification); } }
@GuardedBy("this") void removeCollectedEntry(ReferenceEntry<K, V> entry) { enqueueNotification( entry.getKey(), entry.getHash(), entry.getValueReference().get(), entry.getValueReference().getWeight(), RemovalCause.COLLECTED); writeQueue.remove(entry); accessQueue.remove(entry); }
@Override @GuardedBy("ServiceManagerState.this.monitor") public boolean isSatisfied() { // All services have started or some service has terminated/failed. return states.count(RUNNING) == numberOfServices || states.contains(STOPPING) || states.contains(TERMINATED) || states.contains(FAILED); } }
/** * Drain the key and value reference queues, cleaning up internal entries containing garbage * collected keys or values. */ @GuardedBy("this") void drainReferenceQueues() { if (map.usesKeyReferences()) { drainKeyReferenceQueue(); } if (map.usesValueReferences()) { drainValueReferenceQueue(); } }
/** Sets a new value of an entry. Adds newly created entries at the end of the access queue. */ @GuardedBy("this") void setValue(ReferenceEntry<K, V> entry, K key, V value, long now) { ValueReference<K, V> previous = entry.getValueReference(); int weight = map.weigher.weigh(key, value); checkState(weight >= 0, "Weights must be non-negative"); ValueReference<K, V> valueReference = map.valueStrength.referenceValue(this, entry, value, weight); entry.setValueReference(valueReference); recordWrite(entry, weight, now); previous.notifyNewValue(value); }
@GuardedBy("lock") private void awaitUninterruptibly(Guard guard, boolean signalBeforeWaiting) { if (signalBeforeWaiting) { signalNextWaiter(); } beginWaitingFor(guard); try { do { guard.condition.awaitUninterruptibly(); } while (!guard.isSatisfied()); } finally { endWaitingFor(guard); } }