sapling/eden/fs/utils/Synchronized.h
Andres Suarez fbdb46f5cb Tidy up license headers
Reviewed By: chadaustin

Differential Revision: D17872966

fbshipit-source-id: cd60a364a2146f0dadbeca693b1d4a5d7c97ff63
2019-10-11 05:28:23 -07:00

51 lines
1.4 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#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&) -> std::optional<T>
* update should have type (LockedPtr&) -> 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 *std::move(result);
}
}
auto wlock = state.wlock();
// Check again - something may have raced between the locks.
auto result = check(*wlock);
if (UNLIKELY(bool(result))) {
return *std::move(result);
}
return update(wlock);
}
} // namespace eden
} // namespace facebook