/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include #include 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 class CalledOnceMovableOnlyFunction { using T = ReturnT(ArgumentT...); std::function function_; bool wasCalled_; bool wasMovedFrom_; public: explicit CalledOnceMovableOnlyFunction(std::function &&function) : function_(std::move(function)) { wasCalled_ = false; wasMovedFrom_ = false; } ~CalledOnceMovableOnlyFunction() { react_native_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 { react_native_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) { react_native_assert( !wasMovedFrom_ && "`CalledOnceMovableOnlyFunction` is called after being moved from."); react_native_assert( !wasCalled_ && "`CalledOnceMovableOnlyFunction` is called more than once."); wasCalled_ = true; return function_(args...); } }; } // namespace react } // namespace facebook