@@ -1533,25 +1533,12 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15331533            chainedItem_
15341534                ? &toRecycle_->asChainedItem ().getParentItem (compressor_)
15351535                : nullptr ;
1536-         auto  l_ = chainedItem_ 
1537-                 ? chainedItemLocks_.tryLockExclusive (toRecycleParent_->getKey ())
1538-                 : chainedItemLocks_.tryLockExclusive (toRecycle_->getKey ());
1539-         if  (chainedItem_ && !l_) {
1540-           ++itr;
1541-           continue ;
1542-         }
15431536        Item* candidate_;
15441537        Item* syncItem_;
15451538        // sync on the parent item for chained items to move to next tier
15461539        if  (!lastTier && chainedItem_) {
1547-             if  (&toRecycle_->asChainedItem ().getParentItem (compressor_) !=
1548-                   toRecycleParent_) {
1549-                 ++itr;
1550-                 continue ;
1551-             }
15521540            syncItem_ = toRecycleParent_;
15531541            candidate_ = toRecycle_;
1554-             XDCHECK (l_);
15551542        } else  if  (lastTier && chainedItem_) {
15561543            candidate_ = toRecycleParent_;
15571544            syncItem_ = toRecycleParent_;
@@ -1582,9 +1569,25 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15821569          //  it. We could abort right here, but we need to cleanup in case
15831570          //  unmarkForEviction() returns 0 - so just go through normal path.
15841571          if  (!chainedItem ||
1585-                &toRecycle_->asChainedItem ().getParentItem (compressor_) ==
1586-                    toRecycleParent_) {
1572+              &toRecycle_->asChainedItem ().getParentItem (compressor_) ==
1573+                  toRecycleParent_) {
15871574            mmContainer.remove (itr);
1575+           } else  if  (chainedItem &&
1576+              &toRecycle->asChainedItem ().getParentItem (compressor_) !=
1577+                  toRecycleParent_) {
1578+              auto  ref = syncItem_->unmarkMoving ();
1579+              if  (UNLIKELY (ref == 0 )) {
1580+                wakeUpWaiters (*syncItem_,{});
1581+                const  auto  res =
1582+                    releaseBackToAllocator (*syncItem_, RemoveContext::kNormal , false );
1583+                XDCHECK (res == ReleaseRes::kReleased );
1584+              }
1585+              auto  parentHandle = acquire (syncItem_);
1586+              if  (parentHandle) {
1587+                wakeUpWaiters (*syncItem_,std::move (parentHandle));
1588+              } // in case where parent handle is null that means some other thread
1589+              ++itr;
1590+              continue ;
15881591          }
15891592          return ;
15901593        }
@@ -3052,16 +3055,12 @@ void CacheAllocator<CacheTrait>::releaseSlabImpl(TierId tid,
30523055    auto  startTimeSec = util::getCurrentTimeSec ();
30533056    Item& item = *static_cast <Item*>(alloc);
30543057
3055-     if  (!item.isChainedItem () && !item.hasChainedItem ()) {
3056-       //  TODO: no support for chained items
3057- 
3058-       //  Need to mark an item for release before proceeding
3059-       //  If we can't mark as moving, it means the item is already freed
3060-       const  bool  isAlreadyFreed =
3061-           !markMovingForSlabRelease (releaseContext, alloc, throttler);
3062-       if  (isAlreadyFreed) {
3063-         continue ;
3064-       }
3058+     //  Need to mark an item for release before proceeding
3059+     //  If we can't mark as moving, it means the item is already freed
3060+     const  bool  isAlreadyFreed =
3061+         !markMovingForSlabRelease (releaseContext, alloc, throttler);
3062+     if  (isAlreadyFreed) {
3063+       continue ;
30653064    }
30663065
30673066    //  Try to move this item and make sure we can free the memory
@@ -3326,36 +3325,33 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
33263325      auto & expectedParent = item.asChainedItem ().getParentItem (compressor_);
33273326
33283327      const  std::string parentKey = expectedParent.getKey ().str ();
3328+       // TODO: this might not be needed since we have already marked parent
3329+       //       as moving
33293330      auto  l = chainedItemLocks_.tryLockExclusive (parentKey);
33303331
33313332      if  (!l) {
33323333        continue ;
3333-       } else  if  (expectedParent.getKey () != parentKey) {
3334-         continue ;
3335-       } else  if  (&expectedParent != &item.asChainedItem ().getParentItem (compressor_)) {
3336-         continue ;
3337-       } else  if  (!expectedParent.isAccessible ()) {
3338-         continue ;
3339-       } else  if  (!expectedParent.hasChainedItem ()) {
3340-         continue ;
33413334      }
3335+       XDCHECK_EQ (expectedParent.getKey (),parentKey);
3336+       XDCHECK_EQ (&expectedParent,&item.asChainedItem ().getParentItem (compressor_));
3337+       XDCHECK (expectedParent.isAccessible ());
3338+       XDCHECK (expectedParent.hasChainedItem ());
33423339
33433340      evicted = &expectedParent;
3341+       XDCHECK (evicted->isMoving ());
33443342      token = createPutToken (*evicted);
3345-       if  (evicted->markForEviction ()) {
3346-         XDCHECK_EQ (&expectedParent,&item.asChainedItem ().getParentItem (compressor_));
3347-         //  unmark the child so it will be freed
3348-         //  TODO entire chain just gets evicted since moveForSlabRelease
3349-         //  returns false
3350-         XDCHECK (!item.isMoving ());
3351-         unlinkItemForEviction (*evicted);
3352-         //  wake up any readers that wait for the move to complete
3353-         //  it's safe to do now, as we have the item marked exclusive and
3354-         //  no other reader can be added to the waiters list
3355-         wakeUpWaiters (*evicted, {});
3356-       } else  {
3357-         continue ;
3358-       }
3343+       auto  ret = evicted->markForEvictionWhenMoving ();
3344+       XDCHECK (ret);
3345+       XDCHECK_EQ (&expectedParent,&item.asChainedItem ().getParentItem (compressor_));
3346+       //  unmark the child so it will be freed
3347+       //  TODO entire chain just gets evicted since moveForSlabRelease
3348+       //  returns false
3349+       XDCHECK (!item.isMoving ());
3350+       unlinkItemForEviction (*evicted);
3351+       //  wake up any readers that wait for the move to complete
3352+       //  it's safe to do now, as we have the item marked exclusive and
3353+       //  no other reader can be added to the waiters list
3354+       wakeUpWaiters (*evicted, {});
33593355    } else  {
33603356      evicted = &item;
33613357
@@ -3448,13 +3444,32 @@ bool CacheAllocator<CacheTrait>::markMovingForSlabRelease(
34483444  bool  itemFreed = true ;
34493445  bool  markedMoving = false ;
34503446  TierId tid = getTierId (alloc);
3451-   const  auto  fn = [&markedMoving, &itemFreed](void * memory) {
3447+   const  auto  fn = [this ,  &markedMoving, &itemFreed](void * memory) {
34523448    //  Since this callback is executed, the item is not yet freed
34533449    itemFreed = false ;
34543450    Item* item = static_cast <Item*>(memory);
3455-     XDCHECK (!item->isChainedItem ()); //  TODO: chained items not supported
3456-     if  (item->markMoving ()) {
3457-       markedMoving = true ;
3451+     bool  chainedItem_ = item->isChainedItem ();
3452+     Item* syncItem_ = chainedItem_
3453+                 ? &item->asChainedItem ().getParentItem (compressor_)
3454+                 : item;
3455+     if  (syncItem_->markMoving ()) {
3456+       if  (chainedItem_ &&
3457+               syncItem_ != &item->asChainedItem ().getParentItem (compressor_)) {
3458+           // case where parent changed
3459+           auto  ref = syncItem_->unmarkMoving ();
3460+           if  (UNLIKELY (ref == 0 )) {
3461+             wakeUpWaiters (*syncItem_,{});
3462+             const  auto  res =
3463+                 releaseBackToAllocator (*syncItem_, RemoveContext::kNormal , false );
3464+             XDCHECK (res == ReleaseRes::kReleased );
3465+           }
3466+           auto  parentHandle = acquire (syncItem_);
3467+           if  (parentHandle) {
3468+             wakeUpWaiters (*syncItem_,std::move (parentHandle));
3469+           } // in case where parent handle is null that means some other thread
3470+       } else  {
3471+         markedMoving = true ;
3472+       }
34583473    }
34593474  };
34603475
0 commit comments