Pull CADisplayLink into a separate file
Reviewed By: javache Differential Revision: D3107921 fb-gh-sync-id: 2982043280f925d390e4bebf3884d4762ac62cc6 fbshipit-source-id: 2982043280f925d390e4bebf3884d4762ac62cc6
This commit is contained in:
parent
68918e8773
commit
2115664456
|
@ -14,8 +14,8 @@
|
|||
#import "RCTBridge+Private.h"
|
||||
#import "RCTBridgeMethod.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTDisplayLink.h"
|
||||
#import "RCTJSCExecutor.h"
|
||||
#import "RCTFrameUpdate.h"
|
||||
#import "RCTJavaScriptLoader.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTModuleData.h"
|
||||
|
@ -56,8 +56,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
NSMutableDictionary<NSString *, RCTModuleData *> *_moduleDataByName;
|
||||
NSArray<RCTModuleData *> *_moduleDataByID;
|
||||
NSArray<Class> *_moduleClassesByID;
|
||||
CADisplayLink *_jsDisplayLink;
|
||||
NSMutableSet<RCTModuleData *> *_frameUpdateObservers;
|
||||
RCTDisplayLink *_displayLink;
|
||||
}
|
||||
|
||||
@synthesize flowID = _flowID;
|
||||
|
@ -81,8 +80,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
_valid = YES;
|
||||
_loading = YES;
|
||||
_pendingCalls = [NSMutableArray new];
|
||||
_frameUpdateObservers = [NSMutableSet new];
|
||||
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
|
||||
_displayLink = [RCTDisplayLink new];
|
||||
|
||||
[RCTBridge setCurrentBridge:self];
|
||||
|
||||
|
@ -409,20 +407,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module
|
||||
withModuleData:(RCTModuleData *)moduleData
|
||||
{
|
||||
if (![_frameUpdateObservers containsObject:moduleData]) {
|
||||
if ([moduleData.moduleClass conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) {
|
||||
[_frameUpdateObservers addObject:moduleData];
|
||||
// Don't access the module instance via moduleData, as this will cause deadlock
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)module;
|
||||
__weak typeof(self) weakSelf = self;
|
||||
__weak typeof(_javaScriptExecutor) weakJavaScriptExecutor = _javaScriptExecutor;
|
||||
observer.pauseCallback = ^{
|
||||
[weakJavaScriptExecutor executeBlockOnJavaScriptQueue:^{
|
||||
[weakSelf updateJSDisplayLinkState];
|
||||
}];
|
||||
};
|
||||
}
|
||||
}
|
||||
[_displayLink registerModuleForFrameUpdates:module withModuleData:moduleData];
|
||||
}
|
||||
|
||||
- (NSString *)moduleConfig
|
||||
|
@ -441,21 +426,6 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
}, NULL);
|
||||
}
|
||||
|
||||
- (void)updateJSDisplayLinkState
|
||||
{
|
||||
RCTAssertJSThread();
|
||||
|
||||
BOOL pauseDisplayLink = YES;
|
||||
for (RCTModuleData *moduleData in _frameUpdateObservers) {
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance;
|
||||
if (!observer.paused) {
|
||||
pauseDisplayLink = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_jsDisplayLink.paused = pauseDisplayLink;
|
||||
}
|
||||
|
||||
- (void)injectJSONConfiguration:(NSString *)configJSON
|
||||
onComplete:(void (^)(NSError *))onComplete
|
||||
{
|
||||
|
@ -492,7 +462,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
|
|||
|
||||
// Register the display link to start sending js calls after everything is setup
|
||||
NSRunLoop *targetRunLoop = [_javaScriptExecutor isKindOfClass:[RCTJSCExecutor class]] ? [NSRunLoop currentRunLoop] : [NSRunLoop mainRunLoop];
|
||||
[_jsDisplayLink addToRunLoop:targetRunLoop forMode:NSRunLoopCommonModes];
|
||||
[_displayLink addToRunLoop:targetRunLoop];
|
||||
|
||||
// Perform the state update and notification on the main thread, so we can't run into
|
||||
// timing issues with RCTRootView
|
||||
|
@ -643,8 +613,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
|||
|
||||
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
|
||||
[_jsDisplayLink invalidate];
|
||||
_jsDisplayLink = nil;
|
||||
[_displayLink invalidate];
|
||||
_displayLink = nil;
|
||||
|
||||
[_javaScriptExecutor invalidate];
|
||||
_javaScriptExecutor = nil;
|
||||
|
@ -656,7 +626,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
|||
_moduleDataByName = nil;
|
||||
_moduleDataByID = nil;
|
||||
_moduleClassesByID = nil;
|
||||
_frameUpdateObservers = nil;
|
||||
_pendingCalls = nil;
|
||||
|
||||
if (_flowIDMap != NULL) {
|
||||
|
@ -1010,30 +979,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (void)_jsThreadUpdate:(CADisplayLink *)displayLink
|
||||
{
|
||||
RCTAssertJSThread();
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTBatchedBridge _jsThreadUpdate:]", nil);
|
||||
|
||||
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
|
||||
for (RCTModuleData *moduleData in _frameUpdateObservers) {
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance;
|
||||
if (!observer.paused) {
|
||||
RCTProfileBeginFlowEvent();
|
||||
[self dispatchBlock:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
[observer didUpdateFrame:frameUpdate];
|
||||
} queue:moduleData.methodQueue];
|
||||
}
|
||||
}
|
||||
|
||||
[self updateJSDisplayLinkState];
|
||||
|
||||
RCTProfileImmediateEvent(0, @"JS Thread Tick", displayLink.timestamp, 'g');
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"objc_call", nil);
|
||||
}
|
||||
|
||||
- (void)startProfiling
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol RCTBridgeModule;
|
||||
@class RCTModuleData;
|
||||
|
||||
@interface RCTDisplayLink : NSObject
|
||||
|
||||
- (instancetype)init;
|
||||
- (void)invalidate;
|
||||
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module
|
||||
withModuleData:(RCTModuleData *)moduleData;
|
||||
- (void)addToRunLoop:(NSRunLoop *)runLoop;
|
||||
|
||||
@end
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTDisplayLink.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <QuartzCore/CADisplayLink.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTFrameUpdate.h"
|
||||
#import "RCTModuleData.h"
|
||||
#import "RCTProfile.h"
|
||||
|
||||
@implementation RCTDisplayLink
|
||||
{
|
||||
CADisplayLink *_jsDisplayLink;
|
||||
NSMutableSet<RCTModuleData *> *_frameUpdateObservers;
|
||||
NSRunLoop *_runLoop;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_frameUpdateObservers = [NSMutableSet new];
|
||||
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerModuleForFrameUpdates:(id<RCTBridgeModule>)module
|
||||
withModuleData:(RCTModuleData *)moduleData
|
||||
{
|
||||
if ([_frameUpdateObservers containsObject:moduleData] ||
|
||||
![moduleData.moduleClass conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) {
|
||||
return;
|
||||
}
|
||||
|
||||
[_frameUpdateObservers addObject:moduleData];
|
||||
// Don't access the module instance via moduleData, as this will cause deadlock
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)module;
|
||||
__weak typeof(self) weakSelf = self;
|
||||
observer.pauseCallback = ^{
|
||||
typeof(self) strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
CFRunLoopRef cfRunLoop = [strongSelf->_runLoop getCFRunLoop];
|
||||
|
||||
if (!_runLoop) {
|
||||
return;
|
||||
}
|
||||
|
||||
CFRunLoopPerformBlock(cfRunLoop, kCFRunLoopDefaultMode, ^{
|
||||
[weakSelf updateJSDisplayLinkState];
|
||||
});
|
||||
CFRunLoopWakeUp(cfRunLoop);
|
||||
};
|
||||
}
|
||||
|
||||
- (void)addToRunLoop:(NSRunLoop *)runLoop
|
||||
{
|
||||
_runLoop = runLoop;
|
||||
[_jsDisplayLink addToRunLoop:runLoop forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[_jsDisplayLink invalidate];
|
||||
}
|
||||
|
||||
- (void)assertOnRunLoop
|
||||
{
|
||||
RCTAssert(_runLoop == [NSRunLoop currentRunLoop],
|
||||
@"This method must be called on the CADisplayLink run loop");
|
||||
}
|
||||
|
||||
- (void)dispatchBlock:(dispatch_block_t)block
|
||||
queue:(dispatch_queue_t)queue
|
||||
{
|
||||
if (queue == RCTJSThread) {
|
||||
block();
|
||||
} else if (queue) {
|
||||
dispatch_async(queue, block);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_jsThreadUpdate:(CADisplayLink *)displayLink
|
||||
{
|
||||
[self assertOnRunLoop];
|
||||
|
||||
RCT_PROFILE_BEGIN_EVENT(0, @"-[RCTDisplayLink _jsThreadUpdate:]", nil);
|
||||
|
||||
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
|
||||
for (RCTModuleData *moduleData in _frameUpdateObservers) {
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance;
|
||||
if (!observer.paused) {
|
||||
RCTProfileBeginFlowEvent();
|
||||
|
||||
[self dispatchBlock:^{
|
||||
RCTProfileEndFlowEvent();
|
||||
[observer didUpdateFrame:frameUpdate];
|
||||
} queue:moduleData.methodQueue];
|
||||
}
|
||||
}
|
||||
|
||||
[self updateJSDisplayLinkState];
|
||||
|
||||
RCTProfileImmediateEvent(0, @"JS Thread Tick", displayLink.timestamp, 'g');
|
||||
|
||||
RCT_PROFILE_END_EVENT(0, @"objc_call", nil);
|
||||
}
|
||||
|
||||
- (void)updateJSDisplayLinkState
|
||||
{
|
||||
[self assertOnRunLoop];
|
||||
|
||||
BOOL pauseDisplayLink = YES;
|
||||
for (RCTModuleData *moduleData in _frameUpdateObservers) {
|
||||
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance;
|
||||
if (!observer.paused) {
|
||||
pauseDisplayLink = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_jsDisplayLink.paused = pauseDisplayLink;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue