/** * Allow a Node which was allocated as unevictable to be evictable, as the least recently * used. */ void makeEvictableNow(final Node node) { acquireExclusive(); try { // See comment in the makeEvictable method. if (mMaxSize != 0 && node.mLessUsed == null) { doMakeEvictableNow(node); } } finally { releaseExclusive(); } }
int size() { acquireShared(); int size = mSize; releaseShared(); return size; }
/** * Allow a Node which was allocated as evictable to be unevictable. */ void makeUnevictable(final Node node) { acquireExclusive(); try { if (mMaxSize != 0) { doMakeUnevictable(node); } } finally { releaseExclusive(); } }
acquireExclusive(); return doAllocLatchedNode(null, mode); } else if (node == null) { break; return doAllocLatchedNode(null, mode); } else if ((mode & MODE_NO_EVICT) != 0) { node.releaseExclusive(); releaseExclusive(); node.mUsageList.makeUnevictable(node); acquireExclusive(); } else if ((mode & MODE_NO_EVICT) != 0) { if (node.mCachedState != CACHED_CLEAN) { NodeUsageList usageList = node.mUsageList; if (usageList == this) { doMakeUnevictable(node); } else { releaseExclusive(); usageList.makeUnevictable(node); releaseExclusive(); releaseExclusive(); throw e;
/** * Allow a Node which was allocated as unevictable to be evictable, starting off as the * most recently used. */ void makeEvictable(final Node node) { acquireExclusive(); try { // Only insert if not closed and if not already in the list. The node latch doesn't // need to be held, and so a concurrent call to the unused method might insert the // node sooner. if (mMaxSize != 0 && node.mMoreUsed == null) { Node most = mMostRecentlyUsed; if (node != most) { node.mLessUsed = most; if (most == null) { mLeastRecentlyUsed = node; } else { most.mMoreUsed = node; } mMostRecentlyUsed = node; } } } finally { releaseExclusive(); } }
/** * Initialize and preallocate a minimum amount of nodes. * * @param arena optional */ void initialize(Object arena, int min) throws DatabaseException, OutOfMemoryError { while (--min >= 0) { acquireExclusive(); if (mSize >= mMaxSize) { releaseExclusive(); break; } doAllocLatchedNode(arena, 0).releaseExclusive(); } }
/** * Indicate that a non-root node is most recently used. Root node is not managed in usage * list and cannot be evicted. Caller must hold any latch on node. Latch is never released * by this method, even if an exception is thrown. */ void used(final Node node, final ThreadLocalRandom rnd) { // Moving the node in the usage list is expensive for several reasons. First is the // rapid rate at which shared memory is written to. This creates memory access // contention between CPU cores. Second is the garbage collector. The G1 collector in // particular appears to be very sensitive to old generation objects being shuffled // around too much. Finally, latch acquisition itself can cause contention. If the node // is popular, it will get more chances to be identified as most recently used. This // strategy works well enough because cache eviction is always a best-guess approach. if ((rnd.nextLong() & mUsedRate) == 0 && tryAcquireExclusive()) { doUsed(node); } }
/** * Allow a Node which was allocated as unevictable to be evictable, starting off as the * most recently used. */ void makeEvictable() { mUsageList.makeEvictable(this); }
/** * Allow a Node which was allocated as evictable to be unevictable. */ void makeUnevictable() { mUsageList.makeUnevictable(this); }
/** * Allow a Node which was allocated as unevictable to be evictable, as the least recently * used. */ void makeEvictableNow() { mUsageList.makeEvictableNow(this); }
for (NodeUsageList usageList : mUsageLists) { if (usageList != null) { usageList.delete();
acquireExclusive(); return doAllocLatchedNode(null, mode); } else if (node == null) { break; return doAllocLatchedNode(null, mode); } else if ((mode & MODE_NO_EVICT) != 0) { node.releaseExclusive(); releaseExclusive(); node.mUsageList.makeUnevictable(node); acquireExclusive(); } else if ((mode & MODE_NO_EVICT) != 0) { if (node.mCachedState != CACHED_CLEAN) { NodeUsageList usageList = node.mUsageList; if (usageList == this) { doMakeUnevictable(node); } else { releaseExclusive(); usageList.makeUnevictable(node); releaseExclusive(); releaseExclusive(); throw e;
/** * Allow a Node which was allocated as unevictable to be evictable, starting off as the * most recently used. */ void makeEvictable(final Node node) { acquireExclusive(); try { // Only insert if not closed and if not already in the list. The node latch doesn't // need to be held, and so a concurrent call to the unused method might insert the // node sooner. if (mMaxSize != 0 && node.mMoreUsed == null) { Node most = mMostRecentlyUsed; if (node != most) { node.mLessUsed = most; if (most == null) { mLeastRecentlyUsed = node; } else { most.mMoreUsed = node; } mMostRecentlyUsed = node; } } } finally { releaseExclusive(); } }
/** * Initialize and preallocate a minimum amount of nodes. * * @param arena optional */ void initialize(Object arena, int min) throws DatabaseException, OutOfMemoryError { while (--min >= 0) { acquireExclusive(); if (mSize >= mMaxSize) { releaseExclusive(); break; } doAllocLatchedNode(arena, 0).releaseExclusive(); } }
/** * Indicate that a non-root node is most recently used. Root node is not managed in usage * list and cannot be evicted. Caller must hold any latch on node. Latch is never released * by this method, even if an exception is thrown. */ void used(final Node node, final ThreadLocalRandom rnd) { // Moving the node in the usage list is expensive for several reasons. First is the // rapid rate at which shared memory is written to. This creates memory access // contention between CPU cores. Second is the garbage collector. The G1 collector in // particular appears to be very sensitive to old generation objects being shuffled // around too much. Finally, latch acquisition itself can cause contention. If the node // is popular, it will get more chances to be identified as most recently used. This // strategy works well enough because cache eviction is always a best-guess approach. if ((rnd.nextLong() & mUsedRate) == 0 && tryAcquireExclusive()) { doUsed(node); } }
/** * Allow a Node which was allocated as unevictable to be evictable, starting off as the * most recently used. */ void makeEvictable() { mUsageList.makeEvictable(this); }
/** * Allow a Node which was allocated as evictable to be unevictable. */ void makeUnevictable() { mUsageList.makeUnevictable(this); }
/** * Allow a Node which was allocated as unevictable to be evictable, as the least recently * used. */ void makeEvictableNow() { mUsageList.makeEvictableNow(this); }
for (NodeUsageList usageList : mUsageLists) { if (usageList != null) { usageList.delete();
/** * Allow a Node which was allocated as unevictable to be evictable, as the least recently * used. */ void makeEvictableNow(final Node node) { acquireExclusive(); try { // See comment in the makeEvictable method. if (mMaxSize != 0 && node.mLessUsed == null) { doMakeEvictableNow(node); } } finally { releaseExclusive(); } }