Fabric: Proper thread synchronization in MainRunLoopEventBeat
Summary: To dispatch events synchonously on the main thread we still have to block the Message Queue. We actually dispatch events on the Message Queue while the main thread is waiting. Reviewed By: mdvacca Differential Revision: D9799853 fbshipit-source-id: 8033be36f27371ad2f1dc7210d564fbca1174910
This commit is contained in:
parent
238dec2787
commit
4eb9b40979
|
@ -58,8 +58,8 @@ private:
|
||||||
|
|
||||||
SharedContextContainer contextContainer = std::make_shared<ContextContainer>();
|
SharedContextContainer contextContainer = std::make_shared<ContextContainer>();
|
||||||
|
|
||||||
EventBeatFactory synchronousBeatFactory = []() {
|
EventBeatFactory synchronousBeatFactory = [bridge]() {
|
||||||
return std::make_unique<MainRunLoopEventBeat>();
|
return std::make_unique<MainRunLoopEventBeat>(bridge.jsMessageThread);
|
||||||
};
|
};
|
||||||
|
|
||||||
EventBeatFactory asynchronousBeatFactory = [bridge]() {
|
EventBeatFactory asynchronousBeatFactory = [bridge]() {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <CoreFoundation/CFRunLoop.h>
|
#include <CoreFoundation/CFRunLoop.h>
|
||||||
|
#include <cxxreact/MessageQueueThread.h>
|
||||||
#include <fabric/events/EventBeat.h>
|
#include <fabric/events/EventBeat.h>
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
|
@ -20,12 +21,15 @@ class MainRunLoopEventBeat final:
|
||||||
public EventBeat {
|
public EventBeat {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainRunLoopEventBeat();
|
MainRunLoopEventBeat(std::shared_ptr<MessageQueueThread> messageQueueThread);
|
||||||
~MainRunLoopEventBeat();
|
~MainRunLoopEventBeat();
|
||||||
|
|
||||||
void induce() const override;
|
void induce() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void blockMessageQueueAndThenBeat() const;
|
||||||
|
|
||||||
|
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||||
CFRunLoopObserverRef mainRunLoopObserver_;
|
CFRunLoopObserverRef mainRunLoopObserver_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
|
|
||||||
#import "MainRunLoopEventBeat.h"
|
#import "MainRunLoopEventBeat.h"
|
||||||
|
|
||||||
|
#import <mutex>
|
||||||
#import <React/RCTUtils.h>
|
#import <React/RCTUtils.h>
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace react {
|
namespace react {
|
||||||
|
|
||||||
MainRunLoopEventBeat::MainRunLoopEventBeat() {
|
MainRunLoopEventBeat::MainRunLoopEventBeat(std::shared_ptr<MessageQueueThread> messageQueueThread):
|
||||||
|
messageQueueThread_(std::move(messageQueueThread)) {
|
||||||
|
|
||||||
mainRunLoopObserver_ =
|
mainRunLoopObserver_ =
|
||||||
CFRunLoopObserverCreateWithHandler(
|
CFRunLoopObserverCreateWithHandler(
|
||||||
NULL /* allocator */,
|
NULL /* allocator */,
|
||||||
|
@ -18,7 +21,11 @@ MainRunLoopEventBeat::MainRunLoopEventBeat() {
|
||||||
true /* repeats */,
|
true /* repeats */,
|
||||||
0 /* order */,
|
0 /* order */,
|
||||||
^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
|
^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
|
||||||
this->beat();
|
if (!this->isRequested_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->blockMessageQueueAndThenBeat();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -38,9 +45,33 @@ void MainRunLoopEventBeat::induce() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
RCTExecuteOnMainQueue(^{
|
RCTExecuteOnMainQueue(^{
|
||||||
this->beat();
|
this->blockMessageQueueAndThenBeat();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainRunLoopEventBeat::blockMessageQueueAndThenBeat() const {
|
||||||
|
// Note: We need the third mutex to get back to the main thread before
|
||||||
|
// the lambda is finished (because all mutexes are allocated on the stack).
|
||||||
|
|
||||||
|
std::mutex mutex1;
|
||||||
|
std::mutex mutex2;
|
||||||
|
std::mutex mutex3;
|
||||||
|
|
||||||
|
mutex1.lock();
|
||||||
|
mutex2.lock();
|
||||||
|
mutex3.lock();
|
||||||
|
|
||||||
|
messageQueueThread_->runOnQueue([&]() {
|
||||||
|
mutex1.unlock();
|
||||||
|
mutex2.lock();
|
||||||
|
mutex3.unlock();
|
||||||
|
});
|
||||||
|
|
||||||
|
mutex1.lock();
|
||||||
|
beat();
|
||||||
|
mutex2.unlock();
|
||||||
|
mutex3.lock();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace react
|
} // namespace react
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
|
Loading…
Reference in New Issue