iOS:JS operation use seperated thread

This commit is contained in:
pengfei.zhou 2020-05-13 10:02:22 +08:00 committed by osborn
parent 1830acf977
commit 81dfce17fb
4 changed files with 59 additions and 30 deletions

View File

@ -55,7 +55,7 @@ - (DoricRegistry *)registry {
- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args { - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -64,7 +64,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
@ -76,7 +76,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
[array addObject:arg]; [array addObject:arg];
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -85,7 +85,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
@ -108,7 +108,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
arg = va_arg(args, JSValue *); arg = va_arg(args, JSValue *);
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -117,7 +117,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
@ -130,7 +130,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
[array addObject:arg]; [array addObject:arg];
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -139,14 +139,14 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
- (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source { - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -155,14 +155,14 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
- (DoricAsyncResult *)destroyContext:(NSString *)contextId { - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -171,7 +171,7 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }

View File

@ -56,7 +56,7 @@ + (instancetype)instance {
- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args { - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -65,7 +65,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
@ -85,7 +85,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
[array addObject:arg]; [array addObject:arg];
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -94,7 +94,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
} @catch (NSException *exception) { } @catch (NSException *exception) {
[ret setupError:exception]; [ret setupError:exception];
} }
}); }];
return ret; return ret;
} }
@ -117,7 +117,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
arg = va_arg(args, JSValue *); arg = va_arg(args, JSValue *);
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -127,7 +127,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
[ret setupError:exception]; [ret setupError:exception];
[self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]];
} }
}); }];
return ret; return ret;
} }
@ -140,7 +140,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
[array addObject:arg]; [array addObject:arg];
} }
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -150,14 +150,14 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
[ret setupError:exception]; [ret setupError:exception];
[self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]];
} }
}); }];
return ret; return ret;
} }
- (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source { - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -167,14 +167,14 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr
[ret setupError:exception]; [ret setupError:exception];
[self.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; [self.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]];
} }
}); }];
return ret; return ret;
} }
- (DoricAsyncResult *)destroyContext:(NSString *)contextId { - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self; __weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^() { [self.jsExecutor ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
if (!self) return; if (!self) return;
@try { @try {
@ -184,7 +184,7 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
[ret setupError:exception]; [ret setupError:exception];
[self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]];
} }
}); }];
return ret; return ret;
} }

View File

@ -32,7 +32,6 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, strong) id <DoricJSExecutorProtocol> jsExecutor; @property(nonatomic, strong) id <DoricJSExecutorProtocol> jsExecutor;
@property(nonatomic, strong) dispatch_queue_t jsQueue;
@property(nonatomic, strong) DoricRegistry *registry; @property(nonatomic, strong) DoricRegistry *registry;
@ -45,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN
- (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args; - (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args;
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args; - (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args;
- (void)ensureRunOnJSThread:(dispatch_block_t)block;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@ -45,13 +45,16 @@ @interface DoricJSEngine ()
@property(nonatomic, strong) NSMutableDictionary *timers; @property(nonatomic, strong) NSMutableDictionary *timers;
@property(nonatomic, strong) DoricBridgeExtension *bridgeExtension; @property(nonatomic, strong) DoricBridgeExtension *bridgeExtension;
@property(nonatomic, strong) NSDictionary *innerEnvironmentDictionary; @property(nonatomic, strong) NSDictionary *innerEnvironmentDictionary;
@property(nonatomic, strong) NSThread *jsThread;
@property(nonatomic, assign) BOOL destroyed;
@end @end
@implementation DoricJSEngine @implementation DoricJSEngine
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { if (self = [super init]) {
_jsQueue = dispatch_queue_create("doric.jsengine", DISPATCH_QUEUE_SERIAL); _jsThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil];
[_jsThread start];
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
struct utsname systemInfo; struct utsname systemInfo;
uname(&systemInfo); uname(&systemInfo);
@ -72,7 +75,7 @@ - (instancetype)init {
@"deviceBrand": @"Apple", @"deviceBrand": @"Apple",
@"deviceModel": platform, @"deviceModel": platform,
}; };
dispatch_async(_jsQueue, ^() { [self ensureRunOnJSThread:^() {
self.timers = [[NSMutableDictionary alloc] init]; self.timers = [[NSMutableDictionary alloc] init];
self.registry = [[DoricRegistry alloc] init]; self.registry = [[DoricRegistry alloc] init];
self.bridgeExtension = [DoricBridgeExtension new]; self.bridgeExtension = [DoricBridgeExtension new];
@ -80,11 +83,36 @@ - (instancetype)init {
[self initJSEngine]; [self initJSEngine];
[self initJSExecutor]; [self initJSExecutor];
[self initDoricEnvironment]; [self initDoricEnvironment];
}); }];
} }
return self; return self;
} }
- (void)dealloc {
_destroyed = YES;
};
- (void)ensureRunOnJSThread:(dispatch_block_t)block {
if (NSThread.currentThread == _jsThread) {
block();
} else {
[self performSelector:@selector(ensureRunOnJSThread:)
onThread:_jsThread
withObject:[block copy]
waitUntilDone:NO];
}
}
- (void)threadRun {
[[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[NSThread currentThread].name = @"doric.js.engine";
while (!_destroyed) {
@autoreleasepool {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
}
- (void)initJSEngine { - (void)initJSEngine {
[self.registry registerMonitor:[DoricDefaultMonitor new]]; [self.registry registerMonitor:[DoricDefaultMonitor new]];
self.jsExecutor = [DoricJSCoreExecutor new]; self.jsExecutor = [DoricJSCoreExecutor new];
@ -234,7 +262,7 @@ - (void)callbackTimer:(NSTimer *)timer {
NSDictionary *userInfo = timer.userInfo; NSDictionary *userInfo = timer.userInfo;
NSNumber *timerId = [userInfo valueForKey:@"timerId"]; NSNumber *timerId = [userInfo valueForKey:@"timerId"];
NSNumber *repeat = [userInfo valueForKey:@"repeat"]; NSNumber *repeat = [userInfo valueForKey:@"repeat"];
dispatch_async(self.jsQueue, ^() { [self ensureRunOnJSThread:^{
__strong typeof(_self) self = _self; __strong typeof(_self) self = _self;
@try { @try {
[self invokeDoricMethod:DORIC_TIMER_CALLBACK, timerId, nil]; [self invokeDoricMethod:DORIC_TIMER_CALLBACK, timerId, nil];
@ -246,6 +274,6 @@ - (void)callbackTimer:(NSTimer *)timer {
if (![repeat boolValue]) { if (![repeat boolValue]) {
[self.timers removeObjectForKey:[timerId stringValue]]; [self.timers removeObjectForKey:[timerId stringValue]];
} }
}); }];
} }
@end @end