Fabric: Unifying retain/release logic in EventTarget
Summary: I read my code and one thing stroke me: What if the same event emitter dispatches several events during the same event beat? In the previous implementation, only the first one will be delivered because the first `release` call consumes stored strong reference. So, I changed the API a bit to make this more explicit: we have `retain` & `release` methods and we have a getter that works (multiple times) only if the object was successfully retained. Reviewed By: sahrens Differential Revision: D13668147 fbshipit-source-id: c00af5f15bc7e30aa704d46bd23584b918b6f75a
This commit is contained in:
parent
7d630b92dc
commit
8d83d5f8eb
|
@ -53,6 +53,13 @@ void EventQueue::onBeat(jsi::Runtime &runtime) const {
|
|||
eventPipe_(
|
||||
runtime, event.eventTarget.get(), event.type, event.payloadFactory);
|
||||
}
|
||||
|
||||
// No need to lock `EventEmitter::DispatchMutex()` here.
|
||||
for (const auto &event : queue) {
|
||||
if (event.eventTarget) {
|
||||
event.eventTarget->release(runtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -42,11 +42,20 @@ void EventTarget::retain(jsi::Runtime &runtime) const {
|
|||
assert(!strongInstanceHandle_.isUndefined());
|
||||
}
|
||||
|
||||
jsi::Value EventTarget::release(jsi::Runtime &runtime) const {
|
||||
void EventTarget::release(jsi::Runtime &runtime) const {
|
||||
// The method does not use `jsi::Runtime` reference.
|
||||
// It takes it only to ensure thread-safety (if the caller has the reference,
|
||||
// we are on a proper thread).
|
||||
return std::move(strongInstanceHandle_);
|
||||
strongInstanceHandle_ = jsi::Value::null();
|
||||
}
|
||||
|
||||
jsi::Value EventTarget::getInstanceHandle(jsi::Runtime &runtime) const {
|
||||
if (strongInstanceHandle_.isNull()) {
|
||||
// The `instanceHandle` is not retained.
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
return jsi::Value(runtime, strongInstanceHandle_);
|
||||
}
|
||||
|
||||
Tag EventTarget::getTag() const {
|
||||
|
|
|
@ -43,16 +43,21 @@ class EventTarget {
|
|||
void setEnabled(bool enabled) const;
|
||||
|
||||
/*
|
||||
* Creates a strong instance handle from a weak one and stores it inside the
|
||||
* object.
|
||||
* Retains an instance handler by creating a strong reference to it.
|
||||
* If the EventTarget is disabled, does nothing.
|
||||
*/
|
||||
void retain(jsi::Runtime &runtime) const;
|
||||
|
||||
/*
|
||||
* Extract the stored strong instance handle from the object and returns it.
|
||||
* Releases the instance handler by nulling a strong reference to it.
|
||||
*/
|
||||
jsi::Value release(jsi::Runtime &runtime) const;
|
||||
void release(jsi::Runtime &runtime) const;
|
||||
|
||||
/*
|
||||
* Creates and returns the `instanceHandle`.
|
||||
* Returns `null` if the `instanceHandle` is not retained at this moment.
|
||||
*/
|
||||
jsi::Value getInstanceHandle(jsi::Runtime &runtime) const;
|
||||
|
||||
/*
|
||||
* Deprecated. Do not use.
|
||||
|
|
|
@ -74,7 +74,7 @@ void UIManagerBinding::dispatchEvent(
|
|||
|
||||
auto instanceHandle = eventTarget
|
||||
? [&]() {
|
||||
auto instanceHandle = eventTarget->release(runtime);
|
||||
auto instanceHandle = eventTarget->getInstanceHandle(runtime);
|
||||
if (instanceHandle.isUndefined()) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue