@@ -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,7 +898,12 @@ CacheAllocator<CacheTrait>::acquire(Item* it) {
894898
895899  SCOPE_FAIL { stats_.numRefcountOverflow .inc (); };
896900
897-   incRef (*it);
901+   if  (LIKELY (incRef (*it))) {
902+     return  WriteHandle{it, *this };
903+   } else  {
904+     //  item is being evicted
905+     return  WriteHandle{};
906+   }
898907  return  WriteHandle{it, *this };
899908}
900909
@@ -1170,7 +1179,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
11701179
11711180  //  This item has been unlinked from its parent and we're the only
11721181  //  owner of it, so we're done here
1173-   if  (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1182+   if  (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
11741183    return  false ;
11751184  }
11761185
@@ -1201,7 +1210,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12011210
12021211  //  In case someone else had removed this chained item from its parent by now
12031212  //  So we check again to see if the it has been unlinked from its parent
1204-   if  (!oldItem.isInMMContainer () || oldItem.isOnlyExclusive ()) {
1213+   if  (!oldItem.isInMMContainer () || oldItem.isOnlyMoving ()) {
12051214    return  false ;
12061215  }
12071216
@@ -1217,7 +1226,7 @@ bool CacheAllocator<CacheTrait>::moveChainedItem(ChainedItem& oldItem,
12171226  //  parent's chain and the MMContainer.
12181227  auto  oldItemHandle =
12191228      replaceChainedItemLocked (oldItem, std::move (newItemHdl), *parentHandle);
1220-   XDCHECK (oldItemHandle->isExclusive ());
1229+   XDCHECK (oldItemHandle->isMoving ());
12211230  XDCHECK (!oldItemHandle->isInMMContainer ());
12221231
12231232  return  true ;
@@ -1246,7 +1255,7 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12461255            : toRecycle;
12471256
12481257    //  make sure no other thead is evicting the item
1249-     if  (candidate->getRefCount () != 0  || !candidate->markExclusive ()) {
1258+     if  (candidate->getRefCount () != 0  || !candidate->markMoving ()) {
12501259      ++itr;
12511260      continue ;
12521261    }
@@ -1261,11 +1270,11 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12611270              ? advanceIteratorAndTryEvictChainedItem (itr)
12621271              : advanceIteratorAndTryEvictRegularItem (mmContainer, itr);
12631272      evictionSuccessful = toReleaseHandle != nullptr ;
1264-       //  destroy toReleseHandle . The item won't be released to allocator
1265-       //  since we marked it as exclusive .
1273+       //  destroy toReleaseHandle . The item won't be released to allocator
1274+       //  since we marked for eviction .
12661275    }
12671276
1268-     const  auto  ref = candidate->unmarkExclusive ();
1277+     const  auto  ref = candidate->unmarkMoving ();
12691278    if  (ref == 0u ) {
12701279      //  Invalidate iterator since later on we may use this mmContainer
12711280      //  again, which cannot be done unless we drop this iterator
@@ -2352,7 +2361,7 @@ void CacheAllocator<CacheTrait>::releaseSlabImpl(
23522361    //  Need to mark an item for release before proceeding
23532362    //  If we can't mark as moving, it means the item is already freed
23542363    const  bool  isAlreadyFreed =
2355-         !markExclusiveForSlabRelease (releaseContext, alloc, throttler);
2364+         !markMovingForSlabRelease (releaseContext, alloc, throttler);
23562365    if  (isAlreadyFreed) {
23572366      continue ;
23582367    }
@@ -2397,8 +2406,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
23972406    stats_.numMoveAttempts .inc ();
23982407
23992408    //  Nothing to move and the key is likely also bogus for chained items.
2400-     if  (oldItem.isOnlyExclusive ()) {
2401-       oldItem.unmarkExclusive ();
2409+     if  (oldItem.isOnlyMoving ()) {
2410+       oldItem.unmarkMoving ();
24022411      const  auto  res =
24032412          releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
24042413      XDCHECK (res == ReleaseRes::kReleased );
@@ -2437,7 +2446,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
24372446  //  that's identical to this one to replace it. Here we just need to wait
24382447  //  until all users have dropped the item handles before we can proceed.
24392448  startTime = util::getCurrentTimeSec ();
2440-   while  (!oldItem.isOnlyExclusive ()) {
2449+   while  (!oldItem.isOnlyMoving ()) {
24412450    throttleWith (throttler, [&] {
24422451      XLOGF (WARN,
24432452            " Spent {} seconds, slab release still waiting for refcount to " 
@@ -2491,8 +2500,8 @@ CacheAllocator<CacheTrait>::allocateNewItemForOldItem(const Item& oldItem) {
24912500      return  {};
24922501    }
24932502
2494-     //  Set up the destination for the move. Since oldChainedItem would have 
2495-     //  the exclusive bit set , it won't be picked for eviction.
2503+     //  Set up the destination for the move. Since oldChainedItem would be 
2504+     //  marked as moving , it won't be picked for eviction.
24962505    auto  newItemHdl =
24972506        allocateChainedItemInternal (parentHandle, oldChainedItem.getSize ());
24982507    if  (!newItemHdl) {
@@ -2544,7 +2553,7 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
25442553      //  item is still valid.
25452554      const  std::string parentKey =
25462555          oldItem.asChainedItem ().getParentItem (compressor_).getKey ().str ();
2547-       if  (oldItem.isOnlyExclusive ()) {
2556+       if  (oldItem.isOnlyMoving ()) {
25482557        //  If chained item no longer has a refcount, its parent is already
25492558        //  being released, so we abort this try to moving.
25502559        return  false ;
@@ -2574,10 +2583,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
25742583    stats_.numEvictionAttempts .inc ();
25752584
25762585    //  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
2586+     //  nothing needs to be done. We simply need to call unmarkMoving  and free
25782587    //  the item.
2579-     if  (item.isOnlyExclusive ()) {
2580-       item.unmarkExclusive ();
2588+     if  (item.isOnlyMoving ()) {
2589+       item.unmarkMoving ();
25812590      const  auto  res =
25822591          releaseBackToAllocator (item, RemoveContext::kNormal , false );
25832592      XDCHECK (ReleaseRes::kReleased  == res);
@@ -2608,7 +2617,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26082617      stats_.numEvictionSuccesses .inc ();
26092618
26102619      //  we have the last handle. no longer need to hold on to the exclusive bit
2611-       item.unmarkExclusive ();
2620+       item.unmarkMoving ();
26122621
26132622      //  manually decrement the refcount to call releaseBackToAllocator
26142623      const  auto  ref = decRef (*owningHandle);
@@ -2620,7 +2629,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
26202629    }
26212630
26222631    if  (shutDownInProgress_) {
2623-       item.unmarkExclusive ();
2632+       item.unmarkMoving ();
26242633      allocator_->abortSlabRelease (ctx);
26252634      throw  exception::SlabReleaseAborted (
26262635          folly::sformat (" Slab Release aborted while trying to evict" 
@@ -2766,9 +2775,9 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
27662775template  <typename  CacheTrait>
27672776typename  CacheAllocator<CacheTrait>::WriteHandle
27682777CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
2769-   XDCHECK (item.isExclusive ());
2778+   XDCHECK (item.isMoving ());
27702779
2771-   if  (item.isOnlyExclusive ()) {
2780+   if  (item.isOnlyMoving ()) {
27722781    return  WriteHandle{};
27732782  }
27742783
@@ -2780,7 +2789,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
27802789
27812790  //  We remove the item from both access and mm containers. It doesn't matter
27822791  //  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 .
2792+   //  be freed as long as it's marked for eviction .
27842793  auto  handle = accessContainer_->removeIf (item, std::move (predicate));
27852794
27862795  if  (!handle) {
@@ -2804,7 +2813,7 @@ CacheAllocator<CacheTrait>::evictNormalItemForSlabRelease(Item& item) {
28042813template  <typename  CacheTrait>
28052814typename  CacheAllocator<CacheTrait>::WriteHandle
28062815CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
2807-   XDCHECK (child.isExclusive ());
2816+   XDCHECK (child.isMoving ());
28082817
28092818  //  We have the child marked as moving, but dont know anything about the
28102819  //  state of the parent. Unlike the case of regular eviction where we are
@@ -2826,7 +2835,7 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28262835  //  check if the child is still in mmContainer and the expected parent is
28272836  //  valid under the chained item lock.
28282837  if  (expectedParent.getKey () != parentKey || !child.isInMMContainer () ||
2829-       child.isOnlyExclusive () ||
2838+       child.isOnlyMoving () ||
28302839      &expectedParent != &child.getParentItem (compressor_) ||
28312840      !expectedParent.isAccessible () || !expectedParent.hasChainedItem ()) {
28322841    return  {};
@@ -2881,14 +2890,14 @@ CacheAllocator<CacheTrait>::evictChainedItemForSlabRelease(ChainedItem& child) {
28812890
28822891  //  In case someone else had removed this chained item from its parent by now
28832892  //  So we check again to see if it has been unlinked from its parent
2884-   if  (!child.isInMMContainer () || child.isOnlyExclusive ()) {
2893+   if  (!child.isInMMContainer () || child.isOnlyMoving ()) {
28852894    return  {};
28862895  }
28872896
28882897  //  check after removing from the MMContainer that the parent is still not
28892898  //  being marked as moving. If parent is moving, it will release the child
28902899  //  item and we will wait for that.
2891-   if  (parentHandle->isExclusive ()) {
2900+   if  (parentHandle->isMoving ()) {
28922901    return  {};
28932902  }
28942903
@@ -2921,7 +2930,7 @@ bool CacheAllocator<CacheTrait>::removeIfExpired(const ReadHandle& handle) {
29212930}
29222931
29232932template  <typename  CacheTrait>
2924- bool  CacheAllocator<CacheTrait>::markExclusiveForSlabRelease (
2933+ bool  CacheAllocator<CacheTrait>::markMovingForSlabRelease (
29252934    const  SlabReleaseContext& ctx, void * alloc, util::Throttler& throttler) {
29262935  //  MemoryAllocator::processAllocForRelease will execute the callback
29272936  //  if the item is not already free. So there are three outcomes here:
@@ -2940,7 +2949,7 @@ bool CacheAllocator<CacheTrait>::markExclusiveForSlabRelease(
29402949    //  Since this callback is executed, the item is not yet freed
29412950    itemFreed = false ;
29422951    Item* item = static_cast <Item*>(memory);
2943-     if  (item->markExclusive ()) {
2952+     if  (item->markMoving ()) {
29442953      markedMoving = true ;
29452954    }
29462955  };
0 commit comments