@@ -1237,7 +1237,7 @@ CacheAllocator<CacheTrait>::handleWithWaitContextForMovingItem(Item& item) {
1237
1237
}
1238
1238
1239
1239
template <typename CacheTrait>
1240
- size_t CacheAllocator<CacheTrait>::wakeUpWaiters (folly::StringPiece key,
1240
+ size_t CacheAllocator<CacheTrait>::wakeUpWaitersLocked (folly::StringPiece key,
1241
1241
WriteHandle&& handle) {
1242
1242
std::unique_ptr<MoveCtx> ctx;
1243
1243
auto shard = getShardForKey (key);
@@ -1606,7 +1606,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
1606
1606
// wake up any readers that wait for the move to complete
1607
1607
// it's safe to do now, as we have the item marked exclusive and
1608
1608
// no other reader can be added to the waiters list
1609
- wakeUpWaiters (candidate-> getKey (), WriteHandle {});
1609
+ wakeUpWaiters (* candidate, {});
1610
1610
1611
1611
if (token.isValid () && shouldWriteToNvmCacheExclusive (*candidate)) {
1612
1612
nvmCache_->put (*candidate, std::move (token));
@@ -1617,7 +1617,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
1617
1617
XDCHECK (!candidate->isAccessible ());
1618
1618
XDCHECK (candidate->getKey () == evictedToNext->getKey ());
1619
1619
1620
- wakeUpWaiters (candidate-> getKey () , std::move (evictedToNext));
1620
+ wakeUpWaiters (* candidate, std::move (evictedToNext));
1621
1621
}
1622
1622
1623
1623
XDCHECK (!candidate->isMarkedForEviction () && !candidate->isMoving ());
@@ -1706,7 +1706,7 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
1706
1706
if (item.isExpired ()) {
1707
1707
accessContainer_->remove (item);
1708
1708
item.unmarkMoving ();
1709
- return acquire (&item); // TODO: wakeUpWaiters with null handle?
1709
+ return acquire (&item);
1710
1710
}
1711
1711
1712
1712
TierId nextTier = tid; // TODO - calculate this based on some admission policy
@@ -2881,6 +2881,14 @@ void CacheAllocator<CacheTrait>::throttleWith(util::Throttler& t,
2881
2881
}
2882
2882
}
2883
2883
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
+
2884
2892
template <typename CacheTrait>
2885
2893
bool CacheAllocator<CacheTrait>::moveForSlabRelease(
2886
2894
const SlabReleaseContext& ctx, Item& oldItem, util::Throttler& throttler) {
@@ -2899,7 +2907,8 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
2899
2907
2900
2908
// Nothing to move and the key is likely also bogus for chained items.
2901
2909
if (oldItem.isOnlyMoving ()) {
2902
- oldItem.unmarkMoving ();
2910
+ auto ret = unmarkMovingAndWakeUpWaiters (oldItem, {});
2911
+ XDCHECK (ret == 0 );
2903
2912
const auto res =
2904
2913
releaseBackToAllocator (oldItem, RemoveContext::kNormal , false );
2905
2914
XDCHECK (res == ReleaseRes::kReleased );
@@ -2947,8 +2956,9 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
2947
2956
});
2948
2957
}
2949
2958
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
+
2952
2962
const auto allocInfo = allocator_[tid]->getAllocInfo (oldItem.getMemory ());
2953
2963
allocator_[tid]->free (&oldItem);
2954
2964
@@ -3066,9 +3076,26 @@ bool CacheAllocator<CacheTrait>::tryMovingForSlabRelease(
3066
3076
}
3067
3077
}
3068
3078
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
+ }
3072
3099
}
3073
3100
3074
3101
template <typename CacheTrait>
@@ -3081,7 +3108,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3081
3108
stats_.numEvictionAttempts .inc ();
3082
3109
3083
3110
if (shutDownInProgress_) {
3084
- item. unmarkMoving ( );
3111
+ auto ref = unmarkMovingAndWakeUpWaiters (item, {} );
3085
3112
allocator_[getTierId (item)]->abortSlabRelease (ctx);
3086
3113
throw exception::SlabReleaseAborted (
3087
3114
folly::sformat (" Slab Release aborted while trying to evict"
@@ -3105,7 +3132,8 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3105
3132
// nothing needs to be done. We simply need to call unmarkMoving and free
3106
3133
// the item.
3107
3134
if (item.isOnlyMoving ()) {
3108
- item.unmarkMoving ();
3135
+ auto ref = unmarkMovingAndWakeUpWaiters (item, {});
3136
+ XDCHECK (ref == 0 );
3109
3137
const auto res =
3110
3138
releaseBackToAllocator (item, RemoveContext::kNormal , false );
3111
3139
XDCHECK (ReleaseRes::kReleased == res);
@@ -3162,12 +3190,10 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3162
3190
// unmark the child so it will be freed
3163
3191
item.unmarkMoving ();
3164
3192
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, {});
3171
3197
} else {
3172
3198
continue ;
3173
3199
}
@@ -3177,12 +3203,7 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3177
3203
token = createPutToken (*evicted);
3178
3204
if (evicted->markForEvictionWhenMoving ()) {
3179
3205
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, {});
3186
3207
} else {
3187
3208
continue ;
3188
3209
}
0 commit comments