Allow moving SyncCallback (#43268)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43268

We previously restricted all copies and moves of SyncCallback, but that led to unsafe calling paths being added instead to AsyncCallback. Instead, allowing moving of SyncCallback, and document the need for the caller to invoke it safely, so can we remove the unsafe path from AsyncCallback.

Changelog: [General][Changed] Allow moving SyncCallback for advanced use-cases

Reviewed By: christophpurrer

Differential Revision: D54381734

fbshipit-source-id: 5fd797cd4541e507aa68f1e4e76a1be5cae20fbe
This commit is contained in:
Pieter De Baets
2024-03-04 04:11:36 -08:00
committed by Facebook GitHub Bot
parent 24e6722cb4
commit 43c55e98d4
@@ -54,15 +54,6 @@ class AsyncCallback {
callWithFunction(priority, std::move(callImpl));
}
/// Invoke the function write-away as if it was a synchronous function
/// without any synchronization or delegating to JS context.
/// @note Caller is responsible for calling this from within JS context.
void unsafeCallSync(Args... args) const noexcept {
if (callback_) {
(*callback_)(std::forward<Args>(args)...);
}
}
private:
friend Bridging<AsyncCallback>;
@@ -110,6 +101,9 @@ class AsyncCallback {
}
};
// You must ensure that when invoking this you're located on the JS thread, or
// have exclusive control of the JS VM context. If you cannot ensure this, use
// AsyncCallback instead.
template <typename R, typename... Args>
class SyncCallback<R(Args...)> {
public:
@@ -122,9 +116,19 @@ class SyncCallback<R(Args...)> {
rt,
std::move(jsInvoker))) {}
// Disallow moving to prevent function from get called on another thread.
SyncCallback(SyncCallback&&) = delete;
SyncCallback& operator=(SyncCallback&&) = delete;
// Disallow copying, as we can no longer safely destroy the callback
// from the destructor if there's multiple copies
SyncCallback(const SyncCallback&) = delete;
SyncCallback& operator=(const SyncCallback&) = delete;
// Allow move
SyncCallback(SyncCallback&& other) noexcept
: wrapper_(std::move(other.wrapper_)) {}
SyncCallback& operator=(SyncCallback&& other) noexcept {
wrapper_ = std::move(other.wrapper_);
return *this;
}
~SyncCallback() {
if (auto wrapper = wrapper_.lock()) {