From 26d0b05c80e4a3d577b400a61a1bde0200608cf0 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 27 Aug 2018 07:21:06 -0700 Subject: [PATCH] Fabric: MessageQueueEventBeat Summary: @public MessageQueueEventBeat implements particular Event Beat synchronized with Message Queue and calling a callback on the JS thread (aka Message Queue thread). The actual beat is synchronized with the main run loop. Reviewed By: mdvacca Differential Revision: D8886230 fbshipit-source-id: 97ef7d10f705789b4b0cd3a12389db960159f289 --- React/Fabric/Utils/MessageQueueEventBeat.h | 35 ++++++++++++++ React/Fabric/Utils/MessageQueueEventBeat.mm | 52 +++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 React/Fabric/Utils/MessageQueueEventBeat.h create mode 100644 React/Fabric/Utils/MessageQueueEventBeat.mm diff --git a/React/Fabric/Utils/MessageQueueEventBeat.h b/React/Fabric/Utils/MessageQueueEventBeat.h new file mode 100644 index 000000000..d01c5ae06 --- /dev/null +++ b/React/Fabric/Utils/MessageQueueEventBeat.h @@ -0,0 +1,35 @@ +/** + * 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 +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Event beat that associated with MessageQueueThread. + */ +class MessageQueueEventBeat: + public EventBeat { + +public: + MessageQueueEventBeat(const std::shared_ptr &messageQueueThread); + ~MessageQueueEventBeat(); + + void induce() const override; + +private: + const std::shared_ptr messageQueueThread_; + CFRunLoopObserverRef mainRunLoopObserver_; + mutable std::atomic isBusy_ {false}; +}; + +} // namespace react +} // namespace facebook diff --git a/React/Fabric/Utils/MessageQueueEventBeat.mm b/React/Fabric/Utils/MessageQueueEventBeat.mm new file mode 100644 index 000000000..1e340baa8 --- /dev/null +++ b/React/Fabric/Utils/MessageQueueEventBeat.mm @@ -0,0 +1,52 @@ +/** + * 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 "MessageQueueEventBeat.h" + +namespace facebook { +namespace react { + +MessageQueueEventBeat::MessageQueueEventBeat(const std::shared_ptr &messageQueueThread): + messageQueueThread_(messageQueueThread) { + + mainRunLoopObserver_ = + CFRunLoopObserverCreateWithHandler( + NULL /* allocator */, + kCFRunLoopBeforeWaiting /* activities */, + true /* repeats */, + 0 /* order */, + ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { + // Note: We only `induce` beat here; actual beat will be performed on + // a different thread. + this->induce(); + } + ); + + assert(mainRunLoopObserver_); + + CFRunLoopAddObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); +} + +MessageQueueEventBeat::~MessageQueueEventBeat() { + CFRunLoopRemoveObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); + CFRelease(mainRunLoopObserver_); +} + +void MessageQueueEventBeat::induce() const { + if (!isRequested_ || isBusy_) { + return; + } + + isBusy_ = true; + messageQueueThread_->runOnQueue([this]() { + this->beat(); + isBusy_ = false; + }); +} + +} // namespace react +} // namespace facebook