Skip to content

Commit

Permalink
introduce EventEmitter::experimental_flushSync (#43592)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #43592

changelog: [internal]

Exposing experimental API EventEmitter::experimental_flushSync to trigger synchronous event from native. The API will be changed in the future, this is exposed only for experimentation.

Reviewed By: javache

Differential Revision: D54805494

fbshipit-source-id: fb395588cf1dc944a920ec4a2257390552850263
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Mar 22, 2024
1 parent 15a5638 commit 223e6dc
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ namespace facebook::react {
EventDispatcher::EventDispatcher(
const EventQueueProcessor& eventProcessor,
const EventBeat::Factory& asynchronousEventBeatFactory,
const EventBeat::SharedOwnerBox& ownerBox)
: eventQueue_(
EventQueue(eventProcessor, asynchronousEventBeatFactory(ownerBox))) {}
const EventBeat::SharedOwnerBox& ownerBox,
RuntimeScheduler& runtimeScheduler)
: eventQueue_(EventQueue(
eventProcessor,
asynchronousEventBeatFactory(ownerBox),
runtimeScheduler)) {}

void EventDispatcher::dispatchEvent(RawEvent&& rawEvent) const {
// Allows the event listener to interrupt default event dispatch
Expand All @@ -35,6 +38,10 @@ void EventDispatcher::dispatchEvent(RawEvent&& rawEvent) const {
eventQueue_.enqueueEvent(std::move(rawEvent));
}

void EventDispatcher::experimental_flushSync() const {
eventQueue_.experimental_flushSync();
}

void EventDispatcher::dispatchStateUpdate(StateUpdate&& stateUpdate) const {
eventQueue_.enqueueStateUpdate(std::move(stateUpdate));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
namespace facebook::react {

struct RawEvent;
class RuntimeScheduler;

/*
* Represents event-delivery infrastructure.
Expand All @@ -29,13 +30,19 @@ class EventDispatcher {
EventDispatcher(
const EventQueueProcessor& eventProcessor,
const EventBeat::Factory& asynchronousEventBeatFactory,
const EventBeat::SharedOwnerBox& ownerBox);
const EventBeat::SharedOwnerBox& ownerBox,
RuntimeScheduler& runtimeScheduler);

/*
* Dispatches a raw event with given priority using event-delivery pipe.
*/
void dispatchEvent(RawEvent&& rawEvent) const;

/*
* Experimental API exposed to support EventEmitter::experimental_flushSync.
*/
void experimental_flushSync() const;

/*
* Dispatches a raw event with asynchronous batched priority. Before the
* dispatch we make sure that no other RawEvent of same type and same target
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ class EventEmitter {

const SharedEventTarget& getEventTarget() const;

/*
* Experimental API that will change in the future.
*/
template <typename Lambda>
void experimental_flushSync(Lambda syncFunc) const {
auto eventDispatcher = eventDispatcher_.lock();
if (!eventDispatcher) {
return;
}

syncFunc();
eventDispatcher->experimental_flushSync();
}

/*
* Initiates an event delivery process.
* Is used by particular subclasses only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@

#include "EventQueue.h"

#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
#include "EventEmitter.h"
#include "ShadowNodeFamily.h"

namespace facebook::react {

EventQueue::EventQueue(
EventQueueProcessor eventProcessor,
std::unique_ptr<EventBeat> eventBeat)
std::unique_ptr<EventBeat> eventBeat,
RuntimeScheduler& runtimeScheduler)
: eventProcessor_(std::move(eventProcessor)),
eventBeat_(std::move(eventBeat)) {
eventBeat_(std::move(eventBeat)),
runtimeScheduler_(&runtimeScheduler) {
eventBeat_->setBeatCallback(
[this](jsi::Runtime& runtime) { onBeat(runtime); });
}
Expand Down Expand Up @@ -76,10 +79,26 @@ void EventQueue::enqueueStateUpdate(StateUpdate&& stateUpdate) const {
}

void EventQueue::onEnqueue() const {
if (synchronousAccessRequested_) {
// Sync flush has been scheduled, no need to request access to the runtime.
return;
}
eventBeat_->request();
}

void EventQueue::experimental_flushSync() const {
synchronousAccessRequested_ = true;
runtimeScheduler_->executeNowOnTheSameThread([this](jsi::Runtime& runtime) {

This comment has been minimized.

Copy link
@cortinico

cortinico Mar 22, 2024

Contributor

@sammy-SC this broke Android CI

synchronousAccessRequested_ = false;
onBeat(runtime);
});
}

void EventQueue::onBeat(jsi::Runtime& runtime) const {
if (synchronousAccessRequested_) {
// Sync flush has been scheduled, let's yield to it.
return;
}
flushStateUpdates();
flushEvents(runtime);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

namespace facebook::react {

class RuntimeScheduler;

/*
* Event Queue synchronized with given Event Beat and dispatching event
* using given Event Pipe.
Expand All @@ -27,7 +29,8 @@ class EventQueue {
public:
EventQueue(
EventQueueProcessor eventProcessor,
std::unique_ptr<EventBeat> eventBeat);
std::unique_ptr<EventBeat> eventBeat,
RuntimeScheduler& runtimeScheduler);

/*
* Enqueues and (probably later) dispatch a given event.
Expand All @@ -48,6 +51,11 @@ class EventQueue {
*/
void enqueueStateUpdate(StateUpdate&& stateUpdate) const;

/*
* Experimental API exposed to support EventEmitter::experimental_flushSync.
*/
void experimental_flushSync() const;

protected:
/*
* Called on any enqueue operation.
Expand All @@ -67,6 +75,10 @@ class EventQueue {
mutable std::vector<RawEvent> eventQueue_;
mutable std::vector<StateUpdate> stateUpdateQueue_;
mutable std::mutex queueMutex_;

// TODO: T183075253
RuntimeScheduler* runtimeScheduler_;
mutable std::atomic_bool synchronousAccessRequested_{false};
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ Scheduler::Scheduler(
eventDispatcher_->emplace(
EventQueueProcessor(eventPipe, eventPipeConclusion, statePipe),
schedulerToolbox.asynchronousEventBeatFactory,
eventOwnerBox);
eventOwnerBox,
*runtimeScheduler);

// Casting to `std::shared_ptr<EventDispatcher const>`.
auto eventDispatcher =
Expand Down

0 comments on commit 223e6dc

Please sign in to comment.