mirror of
https://github.com/facebook/sapling.git
synced 2024-10-08 07:49:11 +03:00
d0b1ad675d
Summary: I'd misunderstood the point of SharedMutex's upgrade locks - unless they're used in rare paths, they don't allow for increased concurrency. This diff and D7885245 remove all of Eden's ulocks, replacing them with a helper which checks once with an rlock held, and if the check fails, switches to a wlock (and checks again). Reviewed By: yfeldblum Differential Revision: D7886046 fbshipit-source-id: 545bb0dbb4898cbb71412efc6222ef12e4ee374e
53 lines
1.5 KiB
C++
53 lines
1.5 KiB
C++
/*
|
|
* Copyright (c) 2018-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
*/
|
|
#pragma once
|
|
|
|
#include <folly/Synchronized.h>
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
/**
|
|
* Helper function that optimizes for the case where a read-only check on a
|
|
* contended data structure is likely to succeed. It first acquires the
|
|
* synchronized object with an rlock. If check returns a true-ish value, then
|
|
* the result of dereferencing it is returned. Otherwise, a wlock is acquired
|
|
* and update is called.
|
|
*
|
|
* check should have type (const State&) -> folly::Optional<T>
|
|
* update should have type (State&) -> T
|
|
*/
|
|
template <typename Return, typename State, typename CheckFn, typename UpdateFn>
|
|
Return tryRlockCheckBeforeUpdate(
|
|
folly::Synchronized<State>& state,
|
|
CheckFn&& check,
|
|
UpdateFn&& update) {
|
|
// First, acquire the rlock. If the check succeeds, acquiring a wlock is
|
|
// unnecessary.
|
|
{
|
|
auto rlock = state.rlock();
|
|
auto result = check(*rlock);
|
|
if (LIKELY(bool(result))) {
|
|
return *result;
|
|
}
|
|
}
|
|
|
|
auto wlock = state.wlock();
|
|
// Check again - something may have raced between the locks.
|
|
auto result = check(*wlock);
|
|
if (UNLIKELY(bool(result))) {
|
|
return *result;
|
|
}
|
|
|
|
return update(*wlock);
|
|
}
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|