@@ -823,28 +823,29 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
823823
824824 removeFromMMContainer (*head);
825825
826- // If this chained item is marked as exclusive , we will not free it.
827- // We must capture the exclusive state before we do the decRef when
826+ // If this chained item is marked as moving , we will not free it.
827+ // We must capture the moving state before we do the decRef when
828828 // we know the item must still be valid
829- const bool wasExclusive = head->isExclusive ();
829+ const bool wasMoving = head->isMoving ();
830+ XDCHECK (!head->isMarkedForEviction ());
830831
831832 // Decref and check if we were the last reference. Now if the item
832- // was marked exclusive , after decRef, it will be free to be released
833+ // was marked moving , after decRef, it will be free to be released
833834 // by slab release thread
834835 const auto childRef = head->decRef ();
835836
836- // If the item is already exclusive and we already decremented the
837+ // If the item is already moving and we already decremented the
837838 // refcount, we don't need to free this item. We'll let the slab
838839 // release thread take care of that
839- if (!wasExclusive ) {
840+ if (!wasMoving ) {
840841 if (childRef != 0 ) {
841842 throw std::runtime_error (folly::sformat (
842843 " chained item refcount is not zero. We cannot proceed! "
843844 " Ref: {}, Chained Item: {}" ,
844845 childRef, head->toString ()));
845846 }
846847
847- // Item is not exclusive and refcount is 0, we can proceed to
848+ // Item is not moving and refcount is 0, we can proceed to
848849 // free it or recylce the memory
849850 if (head == toRecycle) {
850851 XDCHECK (ReleaseRes::kReleased != res);
@@ -872,9 +873,12 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
872873}
873874
874875template <typename CacheTrait>
875- void CacheAllocator<CacheTrait>::incRef(Item& it) {
876- it.incRef ();
877- ++handleCount_.tlStats ();
876+ bool CacheAllocator<CacheTrait>::incRef(Item& it) {
877+ if (it.incRef ()) {
878+ ++handleCount_.tlStats ();
879+ return true ;
880+ }
881+ return false ;
878882}
879883
880884template <typename CacheTrait>
@@ -894,8 +898,12 @@ CacheAllocator<CacheTrait>::acquire(Item* it) {
894898
895899 SCOPE_FAIL { stats_.numRefcountOverflow .inc (); };
896900
897- incRef (*it);
898- return WriteHandle{it, *this };
901+ if (LIKELY (incRef (*it))) {
902+ return WriteHandle{it, *this };
903+ } else {
904+ // item is being evicted
905+ return WriteHandle{};
906+ }
899907}
900908
901909template <typename CacheTrait>
@@ -1170,7 +1178,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
11701178
11711179 // This item has been unlinked from its parent and we're the only
11721180 // owner of it, so we're done here
1173- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1181+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
11741182 return false ;
11751183 }
11761184
@@ -1201,7 +1209,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12011209
12021210 // In case someone else had removed this chained item from its parent by now
12031211 // So we check again to see if the it has been unlinked from its parent
1204- if (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1212+ if (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
12051213 return false ;
12061214 }
12071215
@@ -1217,7 +1225,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12171225 // parent's chain and the MMContainer.
12181226 auto oldItemHandle =
12191227 replaceChainedItemLocked (oldItem, std::move (newItemHdl), *parentHandle);
1220- XDCHECK (oldItemHandle->isExclusive ());
1228+ XDCHECK (oldItemHandle->isMoving ());
12211229 XDCHECK (!oldItemHandle->isInMMContainer ());
12221230
12231231 return true ;
@@ -1246,7 +1254,7 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12461254 : toRecycle;
12471255
12481256 // make sure no other thead is evicting the item
1249- if (candidate->getRefCount () != 0 || !candidate->markExclusive ()) {
1257+ if (candidate->getRefCount () != 0 || !candidate->markMoving ()) {
12501258 ++itr;
12511259 continue ;
12521260 }
@@ -1261,11 +1269,11 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12611269 ? advanceIteratorAndTryEvictChainedItem (itr)
12621270 : advanceIteratorAndTryEvictRegularItem (mmContainer, itr);
12631271 evictionSuccessful = toReleaseHandle != nullptr ;
1264- // destroy toReleseHandle . The item won't be released to allocator
1265- // since we marked it as exclusive .
1272+ // destroy toReleaseHandle . The item won't be released to allocator
1273+ // since we marked for eviction .
12661274 }
12671275
1268- const auto ref = candidate->unmarkExclusive ();
1276+ const auto ref = candidate->unmarkMoving ();
12691277 if (ref == 0u ) {
12701278 // Invalidate iterator since later on we may use this mmContainer
12711279 // again, which cannot be done unless we drop this iterator
@@ -2352,7 +2360,7 @@ void CacheAllocator<CacheTrait>::releaseSlabImpl(
23522360 // Need to mark an item for release before proceeding
23532361 // If we can't mark as moving, it means the item is already freed
23542362 const bool isAlreadyFreed =
2355- !markExclusiveForSlabRelease (releaseContext, alloc, throttler);
2363+ !markMovingForSlabRelease (releaseContext, alloc, throttler);
23562364 if (isAlreadyFreed) {
23572365 continue ;
23582366 }
@@ -2397,8 +2405,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
23972405 stats_.numMoveAttempts .inc ();
23982406
23992407 // Nothing to move and the key is likely also bogus for chained items.
2400- if (oldItem.isOnlyExclusive ()) {
2401- oldItem.unmarkExclusive ();
2408+ if (oldItem.isOnlyMoving ()) {
2409+ oldItem.unmarkMoving ();
24022410 const auto res =
24032411 releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
24042412 XDCHECK (res == ReleaseRes::kReleased );
@@ -2437,7 +2445,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
24372445 // that's identical to this one to replace it. Here we just need to wait
24382446 // until all users have dropped the item handles before we can proceed.
24392447 startTime = util::getCurrentTimeSec ();
2440- while (!oldItem.isOnlyExclusive ()) {
2448+ while (!oldItem.isOnlyMoving ()) {
24412449 throttleWith (throttler, [&] {
24422450 XLOGF (WARN,
24432451 " Spent {} seconds, slab release still waiting for refcount to "
@@ -2491,8 +2499,8 @@ CacheAllocator<CacheTrait>::allocateNewItemForOldItem(const Item& oldItem) {
24912499 return {};
24922500 }
24932501
2494- // Set up the destination for the move. Since oldChainedItem would have
2495- // the exclusive bit set , it won't be picked for eviction.
2502+ // Set up the destination for the move. Since oldChainedItem would be
2503+ // marked as moving , it won't be picked for eviction.
24962504 auto newItemHdl =
24972505 allocateChainedItemInternal (parentHandle, oldChainedItem.getSize ());
24982506 if (!newItemHdl) {
@@ -2544,7 +2552,7 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
25442552 // item is still valid.
25452553 const std::string parentKey =
25462554 oldItem.asChainedItem ().getParentItem (compressor_).getKey ().str ();
2547- if (oldItem.isOnlyExclusive ()) {
2555+ if (oldItem.isOnlyMoving ()) {
25482556 // If chained item no longer has a refcount, its parent is already
25492557 // being released, so we abort this try to moving.
25502558 return false ;
@@ -2574,10 +2582,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
25742582 stats_.numEvictionAttempts .inc ();
25752583
25762584 // if the item is already in a state where only the exclusive bit is set,
2577- // nothing needs to be done. We simply need to unmark exclusive bit and free
2585+ // nothing needs to be done. We simply need to call unmarkMoving and free
25782586 // the item.
2579- if (item.isOnlyExclusive ()) {
2580- item.unmarkExclusive ();
2587+ if (item.isOnlyMoving ()) {
2588+ item.unmarkMoving ();
25812589 const auto res =
25822590 releaseBackToAllocator (item, RemoveContext::kNormal , false );
25832591 XDCHECK (ReleaseRes::kReleased == res);
@@ -2608,7 +2616,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26082616 stats_.numEvictionSuccesses .inc ();
26092617
26102618 // we have the last handle. no longer need to hold on to the exclusive bit
2611- item.unmarkExclusive ();
2619+ item.unmarkMoving ();
26122620
26132621 // manually decrement the refcount to call releaseBackToAllocator
26142622 const auto ref = decRef (*owningHandle);
@@ -2620,7 +2628,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26202628 }
26212629
26222630 if (shutDownInProgress_) {
2623- item.unmarkExclusive ();
2631+ item.unmarkMoving ();
26242632 allocator_->abortSlabRelease (ctx);
26252633 throw exception::SlabReleaseAborted (
26262634 folly::sformat (" Slab Release aborted while trying to evict"
@@ -2766,9 +2774,9 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
27662774template <typename CacheTrait>
27672775typename CacheAllocator<CacheTrait>::WriteHandle
27682776CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
2769- XDCHECK (item.isExclusive ());
2777+ XDCHECK (item.isMoving ());
27702778
2771- if (item.isOnlyExclusive ()) {
2779+ if (item.isOnlyMoving ()) {
27722780 return WriteHandle{};
27732781 }
27742782
@@ -2780,7 +2788,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
27802788
27812789 // We remove the item from both access and mm containers. It doesn't matter
27822790 // if someone else calls remove on the item at this moment, the item cannot
2783- // be freed as long as we have the exclusive bit set .
2791+ // be freed as long as it's marked for eviction .
27842792 auto handle = accessContainer_->removeIf (item, std::move (predicate));
27852793
27862794 if (!handle) {
@@ -2804,7 +2812,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
28042812template <typename CacheTrait>
28052813typename CacheAllocator<CacheTrait>::WriteHandle
28062814CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
2807- XDCHECK (child.isExclusive ());
2815+ XDCHECK (child.isMoving ());
28082816
28092817 // We have the child marked as moving, but dont know anything about the
28102818 // state of the parent. Unlike the case of regular eviction where we are
@@ -2826,7 +2834,7 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28262834 // check if the child is still in mmContainer and the expected parent is
28272835 // valid under the chained item lock.
28282836 if (expectedParent.getKey () != parentKey || !child.isInMMContainer () ||
2829- child.isOnlyExclusive () ||
2837+ child.isOnlyMoving () ||
28302838 &expectedParent != &child.getParentItem (compressor_) ||
28312839 !expectedParent.isAccessible () || !expectedParent.hasChainedItem ()) {
28322840 return {};
@@ -2881,14 +2889,14 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28812889
28822890 // In case someone else had removed this chained item from its parent by now
28832891 // So we check again to see if it has been unlinked from its parent
2884- if (!child.isInMMContainer () || child.isOnlyExclusive ()) {
2892+ if (!child.isInMMContainer () || child.isOnlyMoving ()) {
28852893 return {};
28862894 }
28872895
28882896 // check after removing from the MMContainer that the parent is still not
28892897 // being marked as moving. If parent is moving, it will release the child
28902898 // item and we will wait for that.
2891- if (parentHandle->isExclusive ()) {
2899+ if (parentHandle->isMoving ()) {
28922900 return {};
28932901 }
28942902
@@ -2921,7 +2929,7 @@ bool CacheAllocator<CacheTrait>::removeIfExpired(const ReadHandle& handle) {
29212929}
29222930
29232931template <typename CacheTrait>
2924- bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease (
2932+ bool CacheAllocator<CacheTrait>::markMovingForSlabRelease (
29252933 const SlabReleaseContext& ctx, void * alloc, util::Throttler& throttler) {
29262934 // MemoryAllocator::processAllocForRelease will execute the callback
29272935 // if the item is not already free. So there are three outcomes here:
@@ -2940,7 +2948,7 @@ bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease(
29402948 // Since this callback is executed, the item is not yet freed
29412949 itemFreed = false ;
29422950 Item* item = static_cast <Item*>(memory);
2943- if (item->markExclusive ()) {
2951+ if (item->markMoving ()) {
29442952 markedMoving = true ;
29452953 }
29462954 };
0 commit comments