From 5965ba283f4d77dc9efbc1902801d94b6598d715 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 27 Aug 2018 07:21:12 -0700 Subject: [PATCH] Fabric: Introducting EventQueue (+ Batched and Unbatched versions) Summary: @public EventQueue is a queue of events that synchronizing event dispatching with given Event Beat. The only difference between UnbatchedEventQueue and BatchedEventQueue is that UnbatchedEventQueue `induce` an Event Beat right after enqueing an event. Reviewed By: mdvacca Differential Revision: D8886225 fbshipit-source-id: fedba6fdff2ecb6f3c615cea09b5fdaa58890479 --- .../fabric/events/BatchedEventQueue.cpp | 19 +++++++ ReactCommon/fabric/events/BatchedEventQueue.h | 28 ++++++++++ ReactCommon/fabric/events/EventQueue.cpp | 53 +++++++++++++++++++ ReactCommon/fabric/events/EventQueue.h | 48 +++++++++++++++++ .../fabric/events/UnbatchedEventQueue.cpp | 21 ++++++++ .../fabric/events/UnbatchedEventQueue.h | 29 ++++++++++ 6 files changed, 198 insertions(+) create mode 100644 ReactCommon/fabric/events/BatchedEventQueue.cpp create mode 100644 ReactCommon/fabric/events/BatchedEventQueue.h create mode 100644 ReactCommon/fabric/events/EventQueue.cpp create mode 100644 ReactCommon/fabric/events/EventQueue.h create mode 100644 ReactCommon/fabric/events/UnbatchedEventQueue.cpp create mode 100644 ReactCommon/fabric/events/UnbatchedEventQueue.h diff --git a/ReactCommon/fabric/events/BatchedEventQueue.cpp b/ReactCommon/fabric/events/BatchedEventQueue.cpp new file mode 100644 index 000000000..efdcf5005 --- /dev/null +++ b/ReactCommon/fabric/events/BatchedEventQueue.cpp @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "BatchedEventQueue.h" + +namespace facebook { +namespace react { + +void BatchedEventQueue::enqueueEvent(const RawEvent &rawEvent) const { + EventQueue::enqueueEvent(rawEvent); + eventBeat_->request(); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/events/BatchedEventQueue.h b/ReactCommon/fabric/events/BatchedEventQueue.h new file mode 100644 index 000000000..93b2b012f --- /dev/null +++ b/ReactCommon/fabric/events/BatchedEventQueue.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +/* + * Event Queue that dispatches event in batches synchronizing them with + * an Event Beat. + */ +class BatchedEventQueue final: public EventQueue { + +public: + using EventQueue::EventQueue; + + void enqueueEvent(const RawEvent &rawEvent) const override; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/events/EventQueue.cpp b/ReactCommon/fabric/events/EventQueue.cpp new file mode 100644 index 000000000..9d4968cf6 --- /dev/null +++ b/ReactCommon/fabric/events/EventQueue.cpp @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "EventQueue.h" + +#include "EventEmitter.h" + +namespace facebook { +namespace react { + +EventQueue::EventQueue(const EventPipe &eventPipe, std::unique_ptr eventBeat): + eventPipe_(eventPipe), + eventBeat_(std::move(eventBeat)) { + eventBeat_->setBeatCallback(std::bind(&EventQueue::onBeat, this)); + } + +void EventQueue::enqueueEvent(const RawEvent &rawEvent) const { + std::lock_guard lock(queueMutex_); + queue_.push_back(rawEvent); +} + +void EventQueue::onBeat() const { + std::vector queue; + + { + std::lock_guard lock(queueMutex_); + + if (queue_.size() == 0) { + return; + } + + queue = std::move(queue_); + assert(queue_.size() == 0); + } + + { + std::lock_guard lock(EventEmitter::DispatchMutex()); + for (const auto &event : queue) { + eventPipe_( + event.isDispachable() ? event.eventTarget : EmptyEventTarget, + event.type, + event.payload + ); + } + } +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/events/EventQueue.h b/ReactCommon/fabric/events/EventQueue.h new file mode 100644 index 000000000..00952d94b --- /dev/null +++ b/ReactCommon/fabric/events/EventQueue.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Event Queue synchronized with given Event Beat and dispatching event + * using given Event Pipe. + */ +class EventQueue { + +public: + EventQueue(const EventPipe &eventPipe, std::unique_ptr eventBeat); + virtual ~EventQueue() = default; + + /* + * Enqueues and (probably later) dispatch a given event. + * Can be called on any thread. + */ + virtual void enqueueEvent(const RawEvent &rawEvent) const; + +protected: + + void onBeat() const; + + const EventPipe eventPipe_; + const std::unique_ptr eventBeat_; + mutable std::vector queue_; // Thread-safe, protected by `queueMutex_`. + mutable std::mutex queueMutex_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/events/UnbatchedEventQueue.cpp b/ReactCommon/fabric/events/UnbatchedEventQueue.cpp new file mode 100644 index 000000000..4e8a23c5d --- /dev/null +++ b/ReactCommon/fabric/events/UnbatchedEventQueue.cpp @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "UnbatchedEventQueue.h" + +namespace facebook { +namespace react { + +void UnbatchedEventQueue::enqueueEvent(const RawEvent &rawEvent) const { + EventQueue::enqueueEvent(rawEvent); + + eventBeat_->request(); + eventBeat_->induce(); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/events/UnbatchedEventQueue.h b/ReactCommon/fabric/events/UnbatchedEventQueue.h new file mode 100644 index 000000000..4fb51bb48 --- /dev/null +++ b/ReactCommon/fabric/events/UnbatchedEventQueue.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +/* + * Event Queue that dispatches events as granular as possible without waiting + * for the next beat. + */ +class UnbatchedEventQueue final: public EventQueue { + +public: + using EventQueue::EventQueue; + + void enqueueEvent(const RawEvent &rawEvent) const override; +}; + + +} // namespace react +} // namespace facebook