Files
react-native/ReactCommon/utils/CalledOnceMovableOnlyFunction.h
T
Samuel Susla a1b6f7bd9e Fabric: Asserting if the RuntimeExecutor callback in RCTRuntimeExecutorFromBridge is not called
Summary:
The implementation of RuntimeExecutor must execute all provided callbacks. However, the implementation of RCTRuntimeExecutorFromBridge cannot guarantee it because it relies on Bridge to make the call. In this diff, we wrap the callback into a callable that asserts if it's not being called before destruction.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: mdvacca

Differential Revision: D22810439

fbshipit-source-id: f11932019ab6ccbab7e65db5919e0c64dcaf37ed
2020-08-03 10:45:14 -07:00

88 lines
2.2 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <functional>
namespace facebook {
namespace react {
/*
* Implements a moveable-only function that asserts if called more than once
* or destroyed before calling.
* Useful for use in debug mode to ensure such guarantees.
*/
template <typename ReturnT = void, typename... ArgumentT>
class CalledOnceMovableOnlyFunction {
using T = ReturnT(ArgumentT...);
std::function<T> function_;
bool wasCalled_;
bool wasMovedFrom_;
public:
CalledOnceMovableOnlyFunction(std::function<T> &&function)
: function_(std::move(function)) {
wasCalled_ = false;
wasMovedFrom_ = false;
}
~CalledOnceMovableOnlyFunction() {
assert(
(wasCalled_ || wasMovedFrom_) &&
"`CalledOnceMovableOnlyFunction` is destroyed before being called.");
}
/*
* Not copyable.
*/
CalledOnceMovableOnlyFunction(CalledOnceMovableOnlyFunction const &other) =
delete;
CalledOnceMovableOnlyFunction &operator=(
CalledOnceMovableOnlyFunction const &other) = delete;
/*
* Movable.
*/
CalledOnceMovableOnlyFunction(
CalledOnceMovableOnlyFunction &&other) noexcept {
wasCalled_ = false;
wasMovedFrom_ = false;
other.wasMovedFrom_ = true;
function_ = std::move(other.function_);
};
CalledOnceMovableOnlyFunction &operator=(
CalledOnceMovableOnlyFunction &&other) noexcept {
assert(
(wasCalled_ || wasMovedFrom_) &&
"`CalledOnceMovableOnlyFunction` is re-assigned before being called.");
wasCalled_ = false;
wasMovedFrom_ = false;
other.wasMovedFrom_ = true;
function_ = std::move(other.function_);
return *this;
}
/*
* Callable.
*/
ReturnT operator()(ArgumentT... args) {
assert(
!wasMovedFrom_ &&
"`CalledOnceMovableOnlyFunction` is called after being moved from.");
assert(
!wasCalled_ &&
"`CalledOnceMovableOnlyFunction` is called more than once.");
wasCalled_ = true;
return function_(args...);
}
};
} // namespace react
} // namespace facebook