From 380d8cee558c3c20b0000fbb2a9dc8dfca43d16e Mon Sep 17 00:00:00 2001 From: acton393 Date: Tue, 9 Jan 2018 18:17:10 +0800 Subject: [PATCH 1/5] [WEEX-189][iOS] use recursive lock for thread safe collections --- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 2 +- .../Utility/WXThreadSafeMutableArray.m | 107 ++++++++++++++---- .../Utility/WXThreadSafeMutableDictionary.m | 79 ++++++++++--- ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 4 + ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 12 ++ 5 files changed, 163 insertions(+), 41 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index ec069eac94..dc94551521 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -225,7 +225,7 @@ - (void)_handleConfigCenter if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) { BOOL useCoreText = [[configCenter configForKey:@"iOS_weex_ext_config.text_render_useCoreText" defaultValue:@YES isDefault:NULL] boolValue]; [WXTextComponent setRenderUsingCoreText:useCoreText]; - + [WXUtility setThreadSafeCollectionUsingLock:YES]; id sliderConfig = [configCenter configForKey:@"iOS_weex_ext_config.slider_class_name" defaultValue:@"WXCycleSliderComponent" isDefault:NULL]; if(sliderConfig){ NSString *sliderClassName = [WXConvert NSString:sliderConfig]; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m index 421a14dc68..3f8fb40d53 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m @@ -18,11 +18,13 @@ */ #import "WXThreadSafeMutableArray.h" +#import "WXUtility.h" @interface WXThreadSafeMutableArray () @property (nonatomic, strong) dispatch_queue_t queue; @property (nonatomic, strong) NSMutableArray* array; +@property (atomic, strong) NSRecursiveLock * arrayRecursiveLock; @end @@ -34,6 +36,7 @@ - (instancetype)initCommon if (self) { NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.array_%p", self]; _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT); + _arrayRecursiveLock = [[NSRecursiveLock alloc] init]; } return self; } @@ -89,76 +92,131 @@ - (instancetype)initWithObjects:(const id [])objects count:(NSUInteger)cnt - (NSUInteger)count { __block NSUInteger count; - dispatch_sync(_queue, ^{ - count = _array.count; - }); + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_sync(_queue, ^{ + count = _array.count; + }); + } else { + [_arrayRecursiveLock lock]; + count = [_array count]; + [_arrayRecursiveLock unlock]; + } return count; } - (id)objectAtIndex:(NSUInteger)index { __block id obj; - dispatch_sync(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_sync(_queue, ^{ + obj = _array[index]; + }); + } else { + [_arrayRecursiveLock lock]; obj = _array[index]; - }); + [_arrayRecursiveLock unlock]; + } return obj; } - (NSEnumerator *)keyEnumerator { __block NSEnumerator *enu; - dispatch_sync(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_sync(_queue, ^{ + enu = [_array objectEnumerator]; + }); + } else { + [_arrayRecursiveLock lock]; enu = [_array objectEnumerator]; - }); + [_arrayRecursiveLock unlock]; + } return enu; } - (void)insertObject:(id)anObject atIndex:(NSUInteger)index { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_array insertObject:anObject atIndex:index]; + }); + } else { + [_arrayRecursiveLock lock]; [_array insertObject:anObject atIndex:index]; - }); + [_arrayRecursiveLock unlock]; + } } - (void)addObject:(id)anObject; { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_array addObject:anObject]; + }); + } else { + [_arrayRecursiveLock lock]; [_array addObject:anObject]; - }); + [_arrayRecursiveLock unlock]; + } } - (void)removeObjectAtIndex:(NSUInteger)index { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_array removeObjectAtIndex:index]; + }); + } else { + [_arrayRecursiveLock lock]; [_array removeObjectAtIndex:index]; - }); + [_arrayRecursiveLock unlock]; + } } - (void)removeLastObject { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_array removeLastObject]; + }); + } else { + [_arrayRecursiveLock lock]; [_array removeLastObject]; - }); + [_arrayRecursiveLock unlock]; + } } - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_array replaceObjectAtIndex:index withObject:anObject]; + }); + } else { + [_arrayRecursiveLock lock]; [_array replaceObjectAtIndex:index withObject:anObject]; - }); + [_arrayRecursiveLock unlock]; + } } - (NSUInteger)indexOfObject:(id)anObject { __block NSUInteger index = NSNotFound; - dispatch_sync(_queue, ^{ - for (int i = 0; i < [_array count]; i ++) { - if ([_array objectAtIndex:i] == anObject) { - index = i; - break; + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_sync(_queue, ^{ + for (int i = 0; i < [_array count]; i ++) { + if ([_array objectAtIndex:i] == anObject) { + index = i; + break; + } } - } - }); + }); + } else { + [_arrayRecursiveLock lock]; + index = [_array indexOfObject:anObject]; + [_arrayRecursiveLock unlock]; + } + return index; } @@ -167,6 +225,7 @@ - (void)dealloc if (_queue) { _queue = NULL; } + _arrayRecursiveLock = nil; } @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m index d70cf3d0ad..27d1b0779d 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m @@ -18,10 +18,12 @@ */ #import "WXThreadSafeMutableDictionary.h" +#import "WXUtility.h" @interface WXThreadSafeMutableDictionary () @property (nonatomic, strong) dispatch_queue_t queue; +@property (atomic, strong) NSRecursiveLock * recursiveDicLock; @property (nonatomic, strong) NSMutableDictionary* dict; @end @@ -34,6 +36,7 @@ - (instancetype)initCommon if (self) { NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.dictionary_%p", self]; _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT); + _recursiveDicLock = [[NSRecursiveLock alloc] init]; } return self; } @@ -90,56 +93,100 @@ - (instancetype)initWithObjects:(const id [])objects forKeys:(const id)aKey { aKey = [aKey copyWithZone:NULL]; - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ _dict[aKey] = anObject; - }); + }); + } else { + [_recursiveDicLock lock]; + _dict[aKey] = anObject; + [_recursiveDicLock unlock]; + } } - (void)removeObjectForKey:(id)aKey { - dispatch_barrier_async(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_dict removeObjectForKey:aKey]; + }); + } else { + [_recursiveDicLock lock]; [_dict removeObjectForKey:aKey]; - }); + [_recursiveDicLock unlock]; + } } -- (void)removeAllObjects{ - dispatch_barrier_async(_queue, ^{ +- (void)removeAllObjects +{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_barrier_async(_queue, ^{ + [_dict removeAllObjects]; + }); + }else { + [_recursiveDicLock lock]; [_dict removeAllObjects]; - }); + [_recursiveDicLock unlock]; + } } - (id)copy{ __block id copyInstance; - dispatch_sync(_queue, ^{ + if (![WXUtility threadSafeCollectionUsingLock]) { + dispatch_sync(_queue, ^{ + copyInstance = [_dict copy]; + }); + } else { + [_recursiveDicLock lock]; copyInstance = [_dict copy]; - }); + [_recursiveDicLock unlock]; + } + return copyInstance; } diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h index 6577479f2d..0e2bb06c2c 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h @@ -459,4 +459,8 @@ BOOL WXFloatGreaterThanWithPrecision(CGFloat a,CGFloat b,double precision); */ + (NSData *_Nonnull)base64DictToData:(NSDictionary *_Nullable)base64Dict; ++ (void)setThreadSafeCollectionUsingLock:(BOOL)usingLock; + ++ (BOOL)threadSafeCollectionUsingLock; + @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index a96bd848ca..a2e4bddc2c 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -41,6 +41,8 @@ #define KEY_PASSWORD @"com.taobao.Weex.123456" #define KEY_USERNAME_PASSWORD @"com.taobao.Weex.weex123456" +static BOOL threadSafeCollectionUsingLock = NO; + void WXPerformBlockOnMainThread(void (^ _Nonnull block)(void)) { if (!block) return; @@ -135,6 +137,16 @@ CGFloat WXFloorPixelValue(CGFloat value) @implementation WXUtility ++ (void)setThreadSafeCollectionUsingLock:(BOOL)usingLock +{ + threadSafeCollectionUsingLock = usingLock; +} + ++ (BOOL)threadSafeCollectionUsingLock +{ + return threadSafeCollectionUsingLock; +} + + (void)performBlock:(void (^)(void))block onThread:(NSThread *)thread { if (!thread || !block) return; From 5f6eb4e4a428d4a72b7284829bbd9798bcc22f0e Mon Sep 17 00:00:00 2001 From: acton393 Date: Tue, 9 Jan 2018 18:18:22 +0800 Subject: [PATCH 2/5] * [iOS] cancel the default value --- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index dc94551521..ec069eac94 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -225,7 +225,7 @@ - (void)_handleConfigCenter if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) { BOOL useCoreText = [[configCenter configForKey:@"iOS_weex_ext_config.text_render_useCoreText" defaultValue:@YES isDefault:NULL] boolValue]; [WXTextComponent setRenderUsingCoreText:useCoreText]; - [WXUtility setThreadSafeCollectionUsingLock:YES]; + id sliderConfig = [configCenter configForKey:@"iOS_weex_ext_config.slider_class_name" defaultValue:@"WXCycleSliderComponent" isDefault:NULL]; if(sliderConfig){ NSString *sliderClassName = [WXConvert NSString:sliderConfig]; From 114c5d3bd74cde2541f9b5e6ffb571ec51c95165 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 11 Jan 2018 11:06:42 +0800 Subject: [PATCH 3/5] * [iOS] use configCenter for lock --- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index ec069eac94..6d62429fca 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -225,7 +225,8 @@ - (void)_handleConfigCenter if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) { BOOL useCoreText = [[configCenter configForKey:@"iOS_weex_ext_config.text_render_useCoreText" defaultValue:@YES isDefault:NULL] boolValue]; [WXTextComponent setRenderUsingCoreText:useCoreText]; - + BOOL useThreadSafeLock = [[configCenter configForKey:@"iOS_weex_ext_config.useThreadSafeLock" defaultValue:@NO isDefault:NULL] boolValue]; + [WXUtility setThreadSafeCollectionUsingLock:useThreadSafeLock]; id sliderConfig = [configCenter configForKey:@"iOS_weex_ext_config.slider_class_name" defaultValue:@"WXCycleSliderComponent" isDefault:NULL]; if(sliderConfig){ NSString *sliderClassName = [WXConvert NSString:sliderConfig]; From 2c591da8719f464d33681e6fdda8a21fc6b1230c Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 11 Jan 2018 18:06:29 +0800 Subject: [PATCH 4/5] [WEEX-189][iOS] use os_unfair_lock and pthread_mutex here show more details about performance of pthread_mutex and os_unfair_lock https://gist.github.com/misbell/2dc38c47ff56f91c6775dde2be1fceb4 Bug:189 --- .../Utility/WXThreadSafeMutableArray.m | 129 +++++++++++++----- .../Utility/WXThreadSafeMutableDictionary.m | 107 +++++++++++---- 2 files changed, 182 insertions(+), 54 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m index 3f8fb40d53..8ff6641b32 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m @@ -19,12 +19,17 @@ #import "WXThreadSafeMutableArray.h" #import "WXUtility.h" +#import +#import -@interface WXThreadSafeMutableArray () +@interface WXThreadSafeMutableArray () { + pthread_mutex_t _safeThreadArrayMutex; + pthread_mutexattr_t _safeThreadArrayMutexAttr; + os_unfair_lock_t _osUnfairLock; +} @property (nonatomic, strong) dispatch_queue_t queue; @property (nonatomic, strong) NSMutableArray* array; -@property (atomic, strong) NSRecursiveLock * arrayRecursiveLock; @end @@ -36,7 +41,12 @@ - (instancetype)initCommon if (self) { NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.array_%p", self]; _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT); - _arrayRecursiveLock = [[NSRecursiveLock alloc] init]; + pthread_mutexattr_init(&(_safeThreadArrayMutexAttr)); + pthread_mutexattr_settype(&(_safeThreadArrayMutexAttr), PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&(_safeThreadArrayMutex), &(_safeThreadArrayMutexAttr)); + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + _osUnfairLock = &(OS_UNFAIR_LOCK_INIT); + } } return self; } @@ -97,9 +107,15 @@ - (NSUInteger)count count = _array.count; }); } else { - [_arrayRecursiveLock lock]; - count = [_array count]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + count = [_array count]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + count = [_array count]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } return count; } @@ -112,9 +128,15 @@ - (id)objectAtIndex:(NSUInteger)index obj = _array[index]; }); } else { - [_arrayRecursiveLock lock]; - obj = _array[index]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + obj = _array[index]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + obj = _array[index]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } return obj; } @@ -127,9 +149,15 @@ - (NSEnumerator *)keyEnumerator enu = [_array objectEnumerator]; }); } else { - [_arrayRecursiveLock lock]; - enu = [_array objectEnumerator]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + enu = [_array objectEnumerator]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + enu = [_array objectEnumerator]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } return enu; } @@ -141,9 +169,15 @@ - (void)insertObject:(id)anObject atIndex:(NSUInteger)index [_array insertObject:anObject atIndex:index]; }); } else { - [_arrayRecursiveLock lock]; - [_array insertObject:anObject atIndex:index]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + [_array insertObject:anObject atIndex:index]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + [_array insertObject:anObject atIndex:index]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } } @@ -154,9 +188,15 @@ - (void)addObject:(id)anObject; [_array addObject:anObject]; }); } else { - [_arrayRecursiveLock lock]; - [_array addObject:anObject]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + [_array addObject:anObject]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + [_array addObject:anObject]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } } @@ -167,9 +207,15 @@ - (void)removeObjectAtIndex:(NSUInteger)index [_array removeObjectAtIndex:index]; }); } else { - [_arrayRecursiveLock lock]; - [_array removeObjectAtIndex:index]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + [_array removeObjectAtIndex:index]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + [_array removeObjectAtIndex:index]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } } @@ -180,9 +226,15 @@ - (void)removeLastObject [_array removeLastObject]; }); } else { - [_arrayRecursiveLock lock]; - [_array removeLastObject]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + [_array removeLastObject]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + [_array removeLastObject]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } } @@ -193,9 +245,15 @@ - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject [_array replaceObjectAtIndex:index withObject:anObject]; }); } else { - [_arrayRecursiveLock lock]; - [_array replaceObjectAtIndex:index withObject:anObject]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + [_array replaceObjectAtIndex:index withObject:anObject]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + [_array replaceObjectAtIndex:index withObject:anObject]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } } @@ -212,9 +270,15 @@ - (NSUInteger)indexOfObject:(id)anObject } }); } else { - [_arrayRecursiveLock lock]; - index = [_array indexOfObject:anObject]; - [_arrayRecursiveLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_osUnfairLock); + index = [_array indexOfObject:anObject]; + os_unfair_lock_unlock(_osUnfairLock); + } else { + pthread_mutex_lock(&_safeThreadArrayMutex); + index = [_array indexOfObject:anObject]; + pthread_mutex_unlock(&_safeThreadArrayMutex); + } } return index; @@ -225,7 +289,10 @@ - (void)dealloc if (_queue) { _queue = NULL; } - _arrayRecursiveLock = nil; + if ([WXUtility threadSafeCollectionUsingLock]) { + pthread_mutex_destroy(&_safeThreadArrayMutex); + pthread_mutexattr_destroy(&_safeThreadArrayMutexAttr); + } } @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m index 27d1b0779d..0fc1a597c3 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m @@ -19,11 +19,17 @@ #import "WXThreadSafeMutableDictionary.h" #import "WXUtility.h" +#import +#import @interface WXThreadSafeMutableDictionary () +{ + pthread_mutex_t _safeThreadDictionaryMutex; + pthread_mutexattr_t _safeThreadDictionaryMutexAttr; + os_unfair_lock_t _unfairLock; +} @property (nonatomic, strong) dispatch_queue_t queue; -@property (atomic, strong) NSRecursiveLock * recursiveDicLock; @property (nonatomic, strong) NSMutableDictionary* dict; @end @@ -36,7 +42,12 @@ - (instancetype)initCommon if (self) { NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.dictionary_%p", self]; _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT); - _recursiveDicLock = [[NSRecursiveLock alloc] init]; + pthread_mutexattr_init(&(_safeThreadDictionaryMutexAttr)); + pthread_mutexattr_settype(&(_safeThreadDictionaryMutexAttr), PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&(_safeThreadDictionaryMutex), &(_safeThreadDictionaryMutexAttr)); + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + _unfairLock = &(OS_UNFAIR_LOCK_INIT); + } } return self; } @@ -98,9 +109,15 @@ - (NSUInteger)count count = _dict.count; }); } else { - [_recursiveDicLock lock]; - count = [_dict count]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + count = [_dict count]; + os_unfair_lock_unlock(_unfairLock); + } else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + count = [_dict count]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } return count; } @@ -113,9 +130,15 @@ - (id)objectForKey:(id)aKey obj = _dict[aKey]; }); } else { - [_recursiveDicLock lock]; - obj = _dict[aKey]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + obj = _dict[aKey]; + os_unfair_lock_unlock(_unfairLock); + } else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + obj = _dict[aKey]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } return obj; } @@ -128,9 +151,15 @@ - (NSEnumerator *)keyEnumerator enu = [_dict keyEnumerator]; }); } else { - [_recursiveDicLock lock]; - enu = [_dict keyEnumerator]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + enu = [_dict keyEnumerator]; + os_unfair_lock_unlock(_unfairLock); + } else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + enu = [_dict keyEnumerator]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } return enu; } @@ -143,9 +172,15 @@ - (void)setObject:(id)anObject forKey:(id)aKey _dict[aKey] = anObject; }); } else { - [_recursiveDicLock lock]; - _dict[aKey] = anObject; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + _dict[aKey] = anObject; + os_unfair_lock_unlock(_unfairLock); + }else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + _dict[aKey] = anObject; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } } @@ -156,9 +191,15 @@ - (void)removeObjectForKey:(id)aKey [_dict removeObjectForKey:aKey]; }); } else { - [_recursiveDicLock lock]; - [_dict removeObjectForKey:aKey]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + [_dict removeObjectForKey:aKey]; + os_unfair_lock_unlock(_unfairLock); + }else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + [_dict removeObjectForKey:aKey]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } } @@ -169,9 +210,15 @@ - (void)removeAllObjects [_dict removeAllObjects]; }); }else { - [_recursiveDicLock lock]; - [_dict removeAllObjects]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + [_dict removeAllObjects]; + os_unfair_lock_unlock(_unfairLock); + } else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + [_dict removeAllObjects]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } } @@ -182,12 +229,26 @@ - (id)copy{ copyInstance = [_dict copy]; }); } else { - [_recursiveDicLock lock]; - copyInstance = [_dict copy]; - [_recursiveDicLock unlock]; + if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { + os_unfair_lock_lock(_unfairLock); + copyInstance = [_dict copy]; + os_unfair_lock_unlock(_unfairLock); + } else { + pthread_mutex_lock(&_safeThreadDictionaryMutex); + copyInstance = [_dict copy]; + pthread_mutex_unlock(&_safeThreadDictionaryMutex); + } } return copyInstance; } +- (void)dealloc +{ + if ([WXUtility threadSafeCollectionUsingLock]) { + pthread_mutex_destroy(&_safeThreadDictionaryMutex); + pthread_mutexattr_destroy(&_safeThreadDictionaryMutexAttr); + } +} + @end From 78c6dc8623b81e8450e2e12cd6b6dcd01ea999a7 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 11 Jan 2018 19:42:23 +0800 Subject: [PATCH 5/5] [WEEX-189][iOS] use os_unfair_lock and pthread_mutex here show more details about performance of pthread_mutex and os_unfair_lock https://gist.github.com/misbell/2dc38c47ff56f91c6775dde2be1fceb4 Bug:189 --- .../Utility/WXThreadSafeMutableArray.m | 40 +++++++++---------- .../Utility/WXThreadSafeMutableDictionary.m | 32 +++++++-------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m index 8ff6641b32..62a689815c 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableArray.m @@ -25,7 +25,7 @@ @interface WXThreadSafeMutableArray () { pthread_mutex_t _safeThreadArrayMutex; pthread_mutexattr_t _safeThreadArrayMutexAttr; - os_unfair_lock_t _osUnfairLock; + os_unfair_lock _osUnfairLock; } @property (nonatomic, strong) dispatch_queue_t queue; @@ -45,7 +45,7 @@ - (instancetype)initCommon pthread_mutexattr_settype(&(_safeThreadArrayMutexAttr), PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&(_safeThreadArrayMutex), &(_safeThreadArrayMutexAttr)); if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - _osUnfairLock = &(OS_UNFAIR_LOCK_INIT); + _osUnfairLock = OS_UNFAIR_LOCK_INIT; } } return self; @@ -108,9 +108,9 @@ - (NSUInteger)count }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); count = [_array count]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); count = [_array count]; @@ -129,9 +129,9 @@ - (id)objectAtIndex:(NSUInteger)index }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); obj = _array[index]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); obj = _array[index]; @@ -150,9 +150,9 @@ - (NSEnumerator *)keyEnumerator }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); enu = [_array objectEnumerator]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); enu = [_array objectEnumerator]; @@ -170,9 +170,9 @@ - (void)insertObject:(id)anObject atIndex:(NSUInteger)index }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); [_array insertObject:anObject atIndex:index]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); [_array insertObject:anObject atIndex:index]; @@ -189,9 +189,9 @@ - (void)addObject:(id)anObject; }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); [_array addObject:anObject]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); [_array addObject:anObject]; @@ -208,9 +208,9 @@ - (void)removeObjectAtIndex:(NSUInteger)index }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); [_array removeObjectAtIndex:index]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); [_array removeObjectAtIndex:index]; @@ -227,9 +227,9 @@ - (void)removeLastObject }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); [_array removeLastObject]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); [_array removeLastObject]; @@ -246,9 +246,9 @@ - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); [_array replaceObjectAtIndex:index withObject:anObject]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); [_array replaceObjectAtIndex:index withObject:anObject]; @@ -271,9 +271,9 @@ - (NSUInteger)indexOfObject:(id)anObject }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_osUnfairLock); + os_unfair_lock_lock(&_osUnfairLock); index = [_array indexOfObject:anObject]; - os_unfair_lock_unlock(_osUnfairLock); + os_unfair_lock_unlock(&_osUnfairLock); } else { pthread_mutex_lock(&_safeThreadArrayMutex); index = [_array indexOfObject:anObject]; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m index 0fc1a597c3..4086bf4951 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXThreadSafeMutableDictionary.m @@ -26,7 +26,7 @@ @interface WXThreadSafeMutableDictionary () { pthread_mutex_t _safeThreadDictionaryMutex; pthread_mutexattr_t _safeThreadDictionaryMutexAttr; - os_unfair_lock_t _unfairLock; + os_unfair_lock _unfairLock; } @property (nonatomic, strong) dispatch_queue_t queue; @@ -46,7 +46,7 @@ - (instancetype)initCommon pthread_mutexattr_settype(&(_safeThreadDictionaryMutexAttr), PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&(_safeThreadDictionaryMutex), &(_safeThreadDictionaryMutexAttr)); if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - _unfairLock = &(OS_UNFAIR_LOCK_INIT); + _unfairLock = OS_UNFAIR_LOCK_INIT; } } return self; @@ -110,9 +110,9 @@ - (NSUInteger)count }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); count = [_dict count]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); } else { pthread_mutex_lock(&_safeThreadDictionaryMutex); count = [_dict count]; @@ -131,9 +131,9 @@ - (id)objectForKey:(id)aKey }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); obj = _dict[aKey]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); } else { pthread_mutex_lock(&_safeThreadDictionaryMutex); obj = _dict[aKey]; @@ -152,9 +152,9 @@ - (NSEnumerator *)keyEnumerator }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); enu = [_dict keyEnumerator]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); } else { pthread_mutex_lock(&_safeThreadDictionaryMutex); enu = [_dict keyEnumerator]; @@ -173,9 +173,9 @@ - (void)setObject:(id)anObject forKey:(id)aKey }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); _dict[aKey] = anObject; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); }else { pthread_mutex_lock(&_safeThreadDictionaryMutex); _dict[aKey] = anObject; @@ -192,9 +192,9 @@ - (void)removeObjectForKey:(id)aKey }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); [_dict removeObjectForKey:aKey]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); }else { pthread_mutex_lock(&_safeThreadDictionaryMutex); [_dict removeObjectForKey:aKey]; @@ -211,9 +211,9 @@ - (void)removeAllObjects }); }else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); [_dict removeAllObjects]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); } else { pthread_mutex_lock(&_safeThreadDictionaryMutex); [_dict removeAllObjects]; @@ -230,9 +230,9 @@ - (id)copy{ }); } else { if (WX_SYS_VERSION_GREATER_THAN(@"10.0")) { - os_unfair_lock_lock(_unfairLock); + os_unfair_lock_lock(&_unfairLock); copyInstance = [_dict copy]; - os_unfair_lock_unlock(_unfairLock); + os_unfair_lock_unlock(&_unfairLock); } else { pthread_mutex_lock(&_safeThreadDictionaryMutex); copyInstance = [_dict copy];