mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Allow AsyncCallback to be used with lambda (#39717)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/39717 AsyncCallback is a better abstraction than the current usage of WeakCallbackWrapper and RAIICallbackWrapperDestroyer, and has way fewer gotchas. Making a few changes here to make it easier to use in various scenarios and match the behaviour we're already seeing in CallbackWrapper. 1) Remove the explicit copy constructor, since this prevents an automatic move constructor from being generated 2) Add a call variant which takes a lambda, for callers which need to manually create JSI arguments 3) Ignore AsyncCallback invocations when the underlying runtime has gone away. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D49684248 fbshipit-source-id: 8b49ec22cc409572ead80a85b10a190994bf0dd5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f174f028cf
commit
0e10ee6ac6
@@ -29,19 +29,27 @@ class AsyncCallback {
|
||||
std::move(function),
|
||||
std::move(jsInvoker))) {}
|
||||
|
||||
AsyncCallback(const AsyncCallback&) = default;
|
||||
AsyncCallback& operator=(const AsyncCallback&) = default;
|
||||
|
||||
void operator()(Args... args) const {
|
||||
call(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void call(Args... args) const {
|
||||
callInternal(std::nullopt, std::forward<Args>(args)...);
|
||||
callWithArgs(std::nullopt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void callWithPriority(SchedulerPriority priority, Args... args) const {
|
||||
callInternal(priority, std::forward<Args>(args)...);
|
||||
callWithArgs(priority, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void call(
|
||||
std::function<void(jsi::Runtime&, jsi::Function&)>&& callImpl) const {
|
||||
callWithFunction(std::nullopt, std::move(callImpl));
|
||||
}
|
||||
|
||||
void callWithPriority(
|
||||
SchedulerPriority priority,
|
||||
std::function<void(jsi::Runtime&, jsi::Function&)>&& callImpl) const {
|
||||
callWithFunction(priority, std::move(callImpl));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -49,22 +57,39 @@ class AsyncCallback {
|
||||
|
||||
std::shared_ptr<SyncCallback<void(Args...)>> callback_;
|
||||
|
||||
void callInternal(std::optional<SchedulerPriority> priority, Args... args)
|
||||
void callWithArgs(std::optional<SchedulerPriority> priority, Args... args)
|
||||
const {
|
||||
auto wrapper = callback_->wrapper_.lock();
|
||||
if (!wrapper) {
|
||||
throw std::runtime_error("Failed to call invalidated async callback");
|
||||
}
|
||||
auto fn = [callback = callback_,
|
||||
argsPtr = std::make_shared<std::tuple<Args...>>(
|
||||
std::make_tuple(std::forward<Args>(args)...))] {
|
||||
callback->apply(std::move(*argsPtr));
|
||||
};
|
||||
if (wrapper) {
|
||||
auto fn = [callback = callback_,
|
||||
argsPtr = std::make_shared<std::tuple<Args...>>(
|
||||
std::make_tuple(std::forward<Args>(args)...))] {
|
||||
callback->apply(std::move(*argsPtr));
|
||||
};
|
||||
|
||||
if (priority) {
|
||||
wrapper->jsInvoker().invokeAsync(*priority, std::move(fn));
|
||||
} else {
|
||||
wrapper->jsInvoker().invokeAsync(std::move(fn));
|
||||
if (priority) {
|
||||
wrapper->jsInvoker().invokeAsync(*priority, std::move(fn));
|
||||
} else {
|
||||
wrapper->jsInvoker().invokeAsync(std::move(fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void callWithFunction(
|
||||
std::optional<SchedulerPriority> priority,
|
||||
std::function<void(jsi::Runtime&, jsi::Function&)>&& callImpl) const {
|
||||
auto wrapper = callback_->wrapper_.lock();
|
||||
if (wrapper) {
|
||||
auto fn = [wrapper = std::move(wrapper),
|
||||
callImpl = std::move(callImpl)]() {
|
||||
callImpl(wrapper->runtime(), wrapper->callback());
|
||||
};
|
||||
|
||||
if (priority) {
|
||||
wrapper->jsInvoker().invokeAsync(*priority, std::move(fn));
|
||||
} else {
|
||||
wrapper->jsInvoker().invokeAsync(std::move(fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -97,8 +122,15 @@ class SyncCallback<R(Args...)> {
|
||||
|
||||
R call(Args... args) const {
|
||||
auto wrapper = wrapper_.lock();
|
||||
|
||||
// If the wrapper has been deallocated, we can no longer provide a return
|
||||
// value consistently, so our only option is to throw
|
||||
if (!wrapper) {
|
||||
throw std::runtime_error("Failed to call invalidated sync callback");
|
||||
if constexpr (std::is_void_v<R>) {
|
||||
return;
|
||||
} else {
|
||||
throw std::runtime_error("Failed to call invalidated sync callback");
|
||||
}
|
||||
}
|
||||
|
||||
auto& callback = wrapper->callback();
|
||||
|
||||
Reference in New Issue
Block a user