@@ -832,28 +832,29 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
832832
833833 removeFromMMContainer (*head);
834834
835- // If this chained item is marked as exclusive , we will not free it.
836- // We must capture the exclusive state before we do the decRef when
835+ // If this chained item is marked as moving , we will not free it.
836+ // We must capture the moving state before we do the decRef when
837837 // we know the item must still be valid
838- const bool wasExclusive = head->isExclusive ();
838+ const bool wasMoving = head->isMoving ();
839+ XDCHECK (!head->isMarkedForEviction ());
839840
840841 // Decref and check if we were the last reference. Now if the item
841- // was marked exclusive , after decRef, it will be free to be released
842+ // was marked moving , after decRef, it will be free to be released
842843 // by slab release thread
843844 const auto childRef = head->decRef ();
844845
845- // If the item is already exclusive and we already decremented the
846+ // If the item is already moving and we already decremented the
846847 // refcount, we don't need to free this item. We'll let the slab
847848 // release thread take care of that
848- if (!wasExclusive ) {
849+ if (!wasMoving ) {
849850 if (childRef != 0 ) {
850851 throw std::runtime_error (folly::sformat (
851852 " chained item refcount is not zero. We cannot proceed! "
852853 " Ref: {}, Chained Item: {}" ,
853854 childRef, head->toString ()));
854855 }
855856
856- // Item is not exclusive and refcount is 0, we can proceed to
857+ // Item is not moving and refcount is 0, we can proceed to
857858 // free it or recylce the memory
858859 if (head == toRecycle) {
859860 XDCHECK (ReleaseRes::kReleased != res);
@@ -881,9 +882,12 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
881882}
882883
883884template <typename CacheTrait>
884- void CacheAllocator<CacheTrait>::incRef(Item& it) {
885- it.incRef ();
886- ++handleCount_.tlStats ();
885+ bool CacheAllocator<CacheTrait>::incRef(Item& it) {
886+ if (it.incRef ()) {
887+ ++handleCount_.tlStats ();
888+ return true ;
889+ }
890+ return false ;
887891}
888892
889893template <typename CacheTrait>
@@ -903,8 +907,12 @@ CacheAllocator<CacheTrait>::acquire(Item* it) {
903907
904908 SCOPE_FAIL { stats_.numRefcountOverflow .inc (); };
905909
906- incRef (*it);
907- return WriteHandle{it, *this };
910+ if (LIKELY (incRef (*it))) {
911+ return WriteHandle{it, *this };
912+ } else {
913+ // item is being evicted
914+ return WriteHandle{};
915+ }
908916}
909917
910918template <typename CacheTrait>
@@ -1179,7 +1187,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
11791187
11801188 // This item has been unlinked from its parent and we're the only
11811189 // owner of it, so we're done here
1182- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1190+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
11831191 return false ;
11841192 }
11851193
@@ -1210,7 +1218,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12101218
12111219 // In case someone else had removed this chained item from its parent by now
12121220 // So we check again to see if the it has been unlinked from its parent
1213- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1221+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
12141222 return false ;
12151223 }
12161224
@@ -1226,7 +1234,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12261234 // parent's chain and the MMContainer.
12271235 auto oldItemHandle =
12281236 replaceChainedItemLocked (oldItem, std::move (newItemHdl), *parentHandle);
1229- XDCHECK (oldItemHandle->isExclusive ());
1237+ XDCHECK (oldItemHandle->isMoving ());
12301238 XDCHECK (!oldItemHandle->isInMMContainer ());
12311239
12321240 return true ;
@@ -1255,7 +1263,7 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12551263 : toRecycle;
12561264
12571265 // make sure no other thead is evicting the item
1258- if (candidate->getRefCount () != 0 || !candidate->markExclusive ()) {
1266+ if (candidate->getRefCount () != 0 || !candidate->markMoving ()) {
12591267 ++itr;
12601268 continue ;
12611269 }
@@ -1270,11 +1278,11 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12701278 ? advanceIteratorAndTryEvictChainedItem (itr)
12711279 : advanceIteratorAndTryEvictRegularItem (mmContainer, itr);
12721280 evictionSuccessful = toReleaseHandle != nullptr ;
1273- // destroy toReleseHandle . The item won't be released to allocator
1274- // since we marked it as exclusive .
1281+ // destroy toReleaseHandle . The item won't be released to allocator
1282+ // since we marked for eviction .
12751283 }
12761284
1277- const auto ref = candidate->unmarkExclusive ();
1285+ const auto ref = candidate->unmarkMoving ();
12781286 if (ref == 0u ) {
12791287 // Invalidate iterator since later on we may use this mmContainer
12801288 // again, which cannot be done unless we drop this iterator
@@ -2361,7 +2369,7 @@ void CacheAllocator<CacheTrait>::releaseSlabImpl(
23612369 // Need to mark an item for release before proceeding
23622370 // If we can't mark as moving, it means the item is already freed
23632371 const bool isAlreadyFreed =
2364- !markExclusiveForSlabRelease (releaseContext, alloc, throttler);
2372+ !markMovingForSlabRelease (releaseContext, alloc, throttler);
23652373 if (isAlreadyFreed) {
23662374 continue ;
23672375 }
@@ -2406,8 +2414,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
24062414 stats_.numMoveAttempts .inc ();
24072415
24082416 // Nothing to move and the key is likely also bogus for chained items.
2409- if (oldItem.isOnlyExclusive ()) {
2410- oldItem.unmarkExclusive ();
2417+ if (oldItem.isOnlyMoving ()) {
2418+ oldItem.unmarkMoving ();
24112419 const auto res =
24122420 releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
24132421 XDCHECK (res == ReleaseRes::kReleased );
@@ -2446,7 +2454,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
24462454 // that's identical to this one to replace it. Here we just need to wait
24472455 // until all users have dropped the item handles before we can proceed.
24482456 startTime = util::getCurrentTimeSec ();
2449- while (!oldItem.isOnlyExclusive ()) {
2457+ while (!oldItem.isOnlyMoving ()) {
24502458 throttleWith (throttler, [&] {
24512459 XLOGF (WARN,
24522460 " Spent {} seconds, slab release still waiting for refcount to "
@@ -2500,8 +2508,8 @@ CacheAllocator<CacheTrait>::allocateNewItemForOldItem(const Item& oldItem) {
25002508 return {};
25012509 }
25022510
2503- // Set up the destination for the move. Since oldChainedItem would have
2504- // the exclusive bit set , it won't be picked for eviction.
2511+ // Set up the destination for the move. Since oldChainedItem would be
2512+ // marked as moving , it won't be picked for eviction.
25052513 auto newItemHdl =
25062514 allocateChainedItemInternal (parentHandle, oldChainedItem.getSize ());
25072515 if (!newItemHdl) {
@@ -2553,7 +2561,7 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
25532561 // item is still valid.
25542562 const std::string parentKey =
25552563 oldItem.asChainedItem ().getParentItem (compressor_).getKey ().str ();
2556- if (oldItem.isOnlyExclusive ()) {
2564+ if (oldItem.isOnlyMoving ()) {
25572565 // If chained item no longer has a refcount, its parent is already
25582566 // being released, so we abort this try to moving.
25592567 return false ;
@@ -2583,10 +2591,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
25832591 stats_.numEvictionAttempts .inc ();
25842592
25852593 // if the item is already in a state where only the exclusive bit is set,
2586- // nothing needs to be done. We simply need to unmark exclusive bit and free
2594+ // nothing needs to be done. We simply need to call unmarkMoving and free
25872595 // the item.
2588- if (item.isOnlyExclusive ()) {
2589- item.unmarkExclusive ();
2596+ if (item.isOnlyMoving ()) {
2597+ item.unmarkMoving ();
25902598 const auto res =
25912599 releaseBackToAllocator (item, RemoveContext::kNormal , false );
25922600 XDCHECK (ReleaseRes::kReleased == res);
@@ -2617,7 +2625,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26172625 stats_.numEvictionSuccesses .inc ();
26182626
26192627 // we have the last handle. no longer need to hold on to the exclusive bit
2620- item.unmarkExclusive ();
2628+ item.unmarkMoving ();
26212629
26222630 // manually decrement the refcount to call releaseBackToAllocator
26232631 const auto ref = decRef (*owningHandle);
@@ -2629,7 +2637,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26292637 }
26302638
26312639 if (shutDownInProgress_) {
2632- item.unmarkExclusive ();
2640+ item.unmarkMoving ();
26332641 allocator_->abortSlabRelease (ctx);
26342642 throw exception::SlabReleaseAborted (
26352643 folly::sformat (" Slab Release aborted while trying to evict"
@@ -2775,9 +2783,9 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
27752783template <typename CacheTrait>
27762784typename CacheAllocator<CacheTrait>::WriteHandle
27772785CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
2778- XDCHECK (item.isExclusive ());
2786+ XDCHECK (item.isMoving ());
27792787
2780- if (item.isOnlyExclusive ()) {
2788+ if (item.isOnlyMoving ()) {
27812789 return WriteHandle{};
27822790 }
27832791
@@ -2789,7 +2797,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
27892797
27902798 // We remove the item from both access and mm containers. It doesn't matter
27912799 // if someone else calls remove on the item at this moment, the item cannot
2792- // be freed as long as we have the exclusive bit set .
2800+ // be freed as long as it's marked for eviction .
27932801 auto handle = accessContainer_->removeIf (item, std::move (predicate));
27942802
27952803 if (!handle) {
@@ -2813,7 +2821,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
28132821template <typename CacheTrait>
28142822typename CacheAllocator<CacheTrait>::WriteHandle
28152823CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
2816- XDCHECK (child.isExclusive ());
2824+ XDCHECK (child.isMoving ());
28172825
28182826 // We have the child marked as moving, but dont know anything about the
28192827 // state of the parent. Unlike the case of regular eviction where we are
@@ -2835,7 +2843,7 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28352843 // check if the child is still in mmContainer and the expected parent is
28362844 // valid under the chained item lock.
28372845 if (expectedParent.getKey () != parentKey || !child.isInMMContainer () ||
2838- child.isOnlyExclusive () ||
2846+ child.isOnlyMoving () ||
28392847 &expectedParent != &child.getParentItem (compressor_) ||
28402848 !expectedParent.isAccessible () || !expectedParent.hasChainedItem ()) {
28412849 return {};
@@ -2890,14 +2898,14 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28902898
28912899 // In case someone else had removed this chained item from its parent by now
28922900 // So we check again to see if it has been unlinked from its parent
2893- if (!child.isInMMContainer () || child.isOnlyExclusive ()) {
2901+ if (!child.isInMMContainer () || child.isOnlyMoving ()) {
28942902 return {};
28952903 }
28962904
28972905 // check after removing from the MMContainer that the parent is still not
28982906 // being marked as moving. If parent is moving, it will release the child
28992907 // item and we will wait for that.
2900- if (parentHandle->isExclusive ()) {
2908+ if (parentHandle->isMoving ()) {
29012909 return {};
29022910 }
29032911
@@ -2930,7 +2938,7 @@ bool CacheAllocator<CacheTrait>::removeIfExpired(const ReadHandle& handle) {
29302938}
29312939
29322940template <typename CacheTrait>
2933- bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease (
2941+ bool CacheAllocator<CacheTrait>::markMovingForSlabRelease (
29342942 const SlabReleaseContext& ctx, void * alloc, util::Throttler& throttler) {
29352943 // MemoryAllocator::processAllocForRelease will execute the callback
29362944 // if the item is not already free. So there are three outcomes here:
@@ -2949,7 +2957,7 @@ bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease(
29492957 // Since this callback is executed, the item is not yet freed
29502958 itemFreed = false ;
29512959 Item* item = static_cast <Item*>(memory);
2952- if (item->markExclusive ()) {
2960+ if (item->markMoving ()) {
29532961 markedMoving = true ;
29542962 }
29552963 };
0 commit comments