From 673d7e81a2208c28e25ffc5cfec431fa6a74c1e1 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Wed, 28 Dec 2022 10:29:23 -0800 Subject: [PATCH] Avoid using shared_ptr when forwarding arguments in AsyncCallback (#35731) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/35731 [Changelog][Internal] The initial intent was to try and use `unique_ptr` instead of `shared_ptr`, however turns out it complicates code more than it's worth it, so I ended up just factoring the repeated complex parts of the corresponding code to make it easier to reason about. Reviewed By: christophpurrer Differential Revision: D42265274 fbshipit-source-id: 105f57b449934c2e3227e592a76036ca7f61bc35 --- ReactCommon/react/bridging/Function.h | 44 +++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ReactCommon/react/bridging/Function.h b/ReactCommon/react/bridging/Function.h index 4e90410d5d8..568dd59acba 100644 --- a/ReactCommon/react/bridging/Function.h +++ b/ReactCommon/react/bridging/Function.h @@ -39,38 +39,36 @@ class AsyncCallback { } void call(Args... args) const { - auto wrapper = callback_->wrapper_.lock(); - if (!wrapper) { - throw std::runtime_error("Failed to call invalidated async callback"); - } - - auto argsTuple = std::make_tuple(std::forward(args)...); - - wrapper->jsInvoker().invokeAsync( - [callback = callback_, - argsPtr = std::make_shared( - std::move(argsTuple))] { callback->apply(std::move(*argsPtr)); }); + callInternal(std::nullopt, std::forward(args)...); } void callWithPriority(SchedulerPriority priority, Args... args) const { - auto wrapper = callback_->wrapper_.lock(); - if (!wrapper) { - throw std::runtime_error("Failed to call invalidated async callback"); - } - - auto argsTuple = std::make_tuple(std::forward(args)...); - - wrapper->jsInvoker().invokeAsync( - priority, - [callback = callback_, - argsPtr = std::make_shared( - std::move(argsTuple))] { callback->apply(std::move(*argsPtr)); }); + callInternal(priority, std::forward(args)...); } private: friend Bridging; std::shared_ptr> callback_; + + void callInternal(std::optional 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::make_tuple(std::forward(args)...))] { + callback->apply(std::move(*argsPtr)); + }; + + if (priority) { + wrapper->jsInvoker().invokeAsync(*priority, std::move(fn)); + } else { + wrapper->jsInvoker().invokeAsync(std::move(fn)); + } + } }; template