@@ -1237,7 +1237,7 @@ CacheAllocator<CacheTrait>::handleWithWaitContextForMovingItem(Item& item) {
12371237}
12381238
12391239template <typename CacheTrait>
1240- size_t CacheAllocator<CacheTrait>::wakeUpWaiters (folly::StringPiece key,
1240+ size_t CacheAllocator<CacheTrait>::wakeUpWaitersLocked (folly::StringPiece key,
12411241 WriteHandle&& handle) {
12421242 std::unique_ptr<MoveCtx> ctx;
12431243 auto shard = getShardForKey (key);
@@ -1606,7 +1606,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16061606 // wake up any readers that wait for the move to complete
16071607 // it's safe to do now, as we have the item marked exclusive and
16081608 // no other reader can be added to the waiters list
1609- wakeUpWaiters (candidate-> getKey (), WriteHandle {});
1609+ wakeUpWaiters (* candidate, {});
16101610
16111611 if (token.isValid () && shouldWriteToNvmCacheExclusive (*candidate)) {
16121612 nvmCache_->put (*candidate, std::move (token));
@@ -1617,7 +1617,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16171617 XDCHECK (!candidate->isAccessible ());
16181618 XDCHECK (candidate->getKey () == evictedToNext->getKey ());
16191619
1620- wakeUpWaiters (candidate-> getKey () , std::move (evictedToNext));
1620+ wakeUpWaiters (* candidate, std::move (evictedToNext));
16211621 }
16221622
16231623 XDCHECK (!candidate->isMarkedForEviction () && !candidate->isMoving ());
@@ -1706,7 +1706,7 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
17061706 if (item.isExpired ()) {
17071707 accessContainer_->remove (item);
17081708 item.unmarkMoving ();
1709- return acquire (&item); // TODO: wakeUpWaiters with null handle?
1709+ return acquire (&item);
17101710 }
17111711
17121712 TierId nextTier = tid; // TODO - calculate this based on some admission policy
@@ -2881,6 +2881,14 @@ void CacheAllocator<CacheTrait>::throttleWith(util::Throttler& t,
28812881 }
28822882}
28832883
2884+ template <typename CacheTrait>
2885+ typename RefcountWithFlags::Value CacheAllocator<CacheTrait>::unmarkMovingAndWakeUpWaiters(Item &item, WriteHandle handle)
2886+ {
2887+ auto ret = item.unmarkMoving ();
2888+ wakeUpWaiters (item, std::move (handle));
2889+ return ret;
2890+ }
2891+
28842892template <typename CacheTrait>
28852893bool CacheAllocator<CacheTrait>::moveForSlabRelease(
28862894 const SlabReleaseContext& ctx, Item& oldItem, util::Throttler& throttler) {
@@ -2899,7 +2907,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
28992907
29002908 // Nothing to move and the key is likely also bogus for chained items.
29012909 if (oldItem.isOnlyMoving ()) {
2902- oldItem.unmarkMoving ();
2910+ auto ret = unmarkMovingAndWakeUpWaiters (oldItem, {});
2911+ XDCHECK (ret == 0 );
29032912 const auto res =
29042913 releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
29052914 XDCHECK (res == ReleaseRes::kReleased );
@@ -2947,8 +2956,9 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
29472956 });
29482957 }
29492958 auto tid = getTierId (oldItem);
2950- auto ref = oldItem.unmarkMoving ();
2951- XDCHECK_EQ (ref, 0 );
2959+ auto ref = unmarkMovingAndWakeUpWaiters (oldItem, std::move (newItemHdl));
2960+ XDCHECK (ref == 0 );
2961+
29522962 const auto allocInfo = allocator_[tid]->getAllocInfo (oldItem.getMemory ());
29532963 allocator_[tid]->free (&oldItem);
29542964
@@ -3066,9 +3076,26 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
30663076 }
30673077 }
30683078
3069- return oldItem.isChainedItem ()
3070- ? moveChainedItem (oldItem.asChainedItem (), newItemHdl)
3071- : moveRegularItem (oldItem, newItemHdl);
3079+ // TODO: we can unify move*Item and move*ItemWithSync by always
3080+ // using the moving bit to block readers.
3081+ if (getNumTiers () == 1 ) {
3082+ return oldItem.isChainedItem ()
3083+ ? moveChainedItem (oldItem.asChainedItem (), newItemHdl)
3084+ : moveRegularItem (oldItem, newItemHdl);
3085+ } else {
3086+ // TODO: add support for chained items
3087+ moveRegularItemWithSync (oldItem, newItemHdl);
3088+ return true ;
3089+ }
3090+ }
3091+
3092+ template <typename CacheTrait>
3093+ void CacheAllocator<CacheTrait>::wakeUpWaiters(Item& item, WriteHandle handle)
3094+ {
3095+ // readers do not block on 'moving' items in case there is only one tier
3096+ if (getNumTiers () > 1 ) {
3097+ wakeUpWaitersLocked (item.getKey (), std::move (handle));
3098+ }
30723099}
30733100
30743101template <typename CacheTrait>
@@ -3081,7 +3108,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
30813108 stats_.numEvictionAttempts .inc ();
30823109
30833110 if (shutDownInProgress_) {
3084- item. unmarkMoving ( );
3111+ auto ref = unmarkMovingAndWakeUpWaiters (item, {} );
30853112 allocator_[getTierId (item)]->abortSlabRelease (ctx);
30863113 throw exception::SlabReleaseAborted (
30873114 folly::sformat (" Slab Release aborted while trying to evict"
@@ -3105,7 +3132,8 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
31053132 // nothing needs to be done. We simply need to call unmarkMoving and free
31063133 // the item.
31073134 if (item.isOnlyMoving ()) {
3108- item.unmarkMoving ();
3135+ auto ref = unmarkMovingAndWakeUpWaiters (item, {});
3136+ XDCHECK (ref == 0 );
31093137 const auto res =
31103138 releaseBackToAllocator (item, RemoveContext::kNormal , false );
31113139 XDCHECK (ReleaseRes::kReleased == res);
@@ -3162,12 +3190,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
31623190 // unmark the child so it will be freed
31633191 item.unmarkMoving ();
31643192 unlinkItemForEviction (*evicted);
3165- if (getNumTiers () > 1 ) {
3166- // wake up any readers that wait for the move to complete
3167- // it's safe to do now, as we have the item marked exclusive and
3168- // no other reader can be added to the waiters list
3169- wakeUpWaiters (evicted->getKey (), WriteHandle{});
3170- }
3193+ // wake up any readers that wait for the move to complete
3194+ // it's safe to do now, as we have the item marked exclusive and
3195+ // no other reader can be added to the waiters list
3196+ wakeUpWaiters (*evicted, {});
31713197 } else {
31723198 continue ;
31733199 }
@@ -3177,12 +3203,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
31773203 token = createPutToken (*evicted);
31783204 if (evicted->markForEvictionWhenMoving ()) {
31793205 unlinkItemForEviction (*evicted);
3180- if (getNumTiers () > 1 ) {
3181- // wake up any readers that wait for the move to complete
3182- // it's safe to do now, as we have the item marked exclusive and
3183- // no other reader can be added to the waiters list
3184- wakeUpWaiters (evicted->getKey (), WriteHandle{});
3185- }
3206+ wakeUpWaiters (*evicted, {});
31863207 } else {
31873208 continue ;
31883209 }
0 commit comments