Fabric: EventBeat::Owner to help with crashes

Summary:
The purpose of `EventBeat` is handling an asynchronous callback to itself which is being delivered on some different thread. That brings a challenge of ensuring that the `EventBeat` object stays valid during the timeframe of callback execution. The concept of Owner helps with that.
The owner is a shared pointer that retains (probably indirectly) the `EventBeat` object. To ensure the correctness of the call, `EventBeat` retains the owner (practically creating a retain cycle) during executing the callback. In case if the pointer to the owner already null, `EventBeat` skips executing the callback.
It's impossible to retain itself directly or refer to the shared pointer to itself from a constructor. `OwnerBox` is designed to work around this issue; it allows to store the pointer later, right after the creation of some other object that owns an `EventBeat`.

Reviewed By: JoshuaGross

Differential Revision: D17128549

fbshipit-source-id: 7ed34fd865430975157fd362f51c4a3d64214430
This commit is contained in:
Valentin Shergin
2019-08-30 18:24:27 -07:00
committed by Facebook Github Bot
parent 5c39c22187
commit c80192c2ab
13 changed files with 91 additions and 45 deletions
@@ -25,9 +25,11 @@ class AsyncEventBeat : public EventBeat {
friend class EventBeatManager;
AsyncEventBeat(
EventBeat::SharedOwnerBox const &ownerBox,
EventBeatManager* eventBeatManager,
RuntimeExecutor runtimeExecutor,
jni::global_ref<jobject> javaUIManager) :
EventBeat(ownerBox),
eventBeatManager_(eventBeatManager),
runtimeExecutor_(std::move(runtimeExecutor)),
javaUIManager_(javaUIManager) {
@@ -206,16 +206,16 @@ void Binding::installFabricUIManager(
// TODO: T31905686 Create synchronous Event Beat
jni::global_ref<jobject> localJavaUIManager = javaUIManager_;
EventBeatFactory synchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager]() {
EventBeat::Factory synchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager](EventBeat::SharedOwnerBox const &ownerBox) {
return std::make_unique<AsyncEventBeat>(
eventBeatManager, runtimeExecutor, localJavaUIManager);
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
};
EventBeatFactory asynchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager]() {
EventBeat::Factory asynchronousBeatFactory =
[eventBeatManager, runtimeExecutor, localJavaUIManager](EventBeat::SharedOwnerBox const &ownerBox) {
return std::make_unique<AsyncEventBeat>(
eventBeatManager, runtimeExecutor, localJavaUIManager);
ownerBox, eventBeatManager, runtimeExecutor, localJavaUIManager);
};
std::shared_ptr<const ReactNativeConfig> config =