From 114b0801ce4eed8dfd145efcfd101575ccdf6e40 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 1 Aug 2017 02:48:28 -0700 Subject: [PATCH] RCTImage: Use C atomics instead of OSAtomic Summary: The next in my series of :atom: migrations. Closes https://github.com/facebook/react-native/pull/15278 Differential Revision: D5526468 Pulled By: javache fbshipit-source-id: 91511c69bc37a6f1382bcf0b0dd847adf10fd43a --- Libraries/Image/RCTImageLoader.m | 41 +++++++++++++--------- Libraries/Image/RCTImageStoreManager.m | 8 ++--- Libraries/Image/RCTLocalAssetImageLoader.m | 8 ++--- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/Libraries/Image/RCTImageLoader.m b/Libraries/Image/RCTImageLoader.m index a9843548e98..e66a5abbc56 100644 --- a/Libraries/Image/RCTImageLoader.m +++ b/Libraries/Image/RCTImageLoader.m @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import #import #import @@ -324,7 +324,8 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, BOOL requiresScheduling = [loadHandler respondsToSelector:@selector(requiresScheduling)] ? [loadHandler requiresScheduling] : YES; - __block volatile uint32_t cancelled = 0; + __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); + // TODO: Protect this variable shared between threads. __block dispatch_block_t cancelLoad = nil; void (^completionHandler)(NSError *, id, NSString *) = ^(NSError *error, id imageOrData, NSString *fetchDate) { cancelLoad = nil; @@ -338,11 +339,11 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, // Most loaders do not return on the main thread, so caller is probably not // expecting it, and may do expensive post-processing in the callback dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (!cancelled) { + if (!atomic_load(&cancelled)) { completionBlock(error, imageOrData, cacheResult, fetchDate); } }); - } else if (!cancelled) { + } else if (!atomic_load(&cancelled)) { completionBlock(error, imageOrData, cacheResult, fetchDate); } }; @@ -369,7 +370,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, __weak RCTImageLoader *weakSelf = self; dispatch_async(_URLRequestQueue, ^{ __typeof(self) strongSelf = weakSelf; - if (cancelled || !strongSelf) { + if (atomic_load(&cancelled) || !strongSelf) { return; } @@ -392,12 +393,15 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, }); return ^{ + BOOL alreadyCancelled = atomic_fetch_or(&cancelled, 1); + if (alreadyCancelled) { + return; + } dispatch_block_t cancelLoadLocal = cancelLoad; cancelLoad = nil; - if (cancelLoadLocal && !cancelled) { + if (cancelLoadLocal) { cancelLoadLocal(); } - OSAtomicOr32Barrier(1, &cancelled); }; } @@ -524,20 +528,25 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock completionBlock:(RCTImageLoaderCompletionBlock)completionBlock { - __block volatile uint32_t cancelled = 0; + __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); + // TODO: Protect this variable shared between threads. __block dispatch_block_t cancelLoad = nil; dispatch_block_t cancellationBlock = ^{ + BOOL alreadyCancelled = atomic_fetch_or(&cancelled, 1); + if (alreadyCancelled) { + return; + } dispatch_block_t cancelLoadLocal = cancelLoad; - if (cancelLoadLocal && !cancelled) { + cancelLoad = nil; + if (cancelLoadLocal) { cancelLoadLocal(); } - OSAtomicOr32Barrier(1, &cancelled); }; __weak RCTImageLoader *weakSelf = self; void (^completionHandler)(NSError *, id, BOOL, NSString *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate) { __typeof(self) strongSelf = weakSelf; - if (cancelled || !strongSelf) { + if (atomic_load(&cancelled) || !strongSelf) { return; } @@ -606,17 +615,17 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, return ^{}; } - __block volatile uint32_t cancelled = 0; + __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); void (^completionHandler)(NSError *, UIImage *) = ^(NSError *error, UIImage *image) { if (RCTIsMainQueue()) { // Most loaders do not return on the main thread, so caller is probably not // expecting it, and may do expensive post-processing in the callback dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (!cancelled) { + if (!atomic_load(&cancelled)) { completionBlock(error, clipped ? RCTResizeImageIfNeeded(image, size, scale, resizeMode) : image); } }); - } else if (!cancelled) { + } else if (!atomic_load(&cancelled)) { completionBlock(error, clipped ? RCTResizeImageIfNeeded(image, size, scale, resizeMode) : image); } }; @@ -638,7 +647,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, // Do actual decompression on a concurrent background queue dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (!cancelled) { + if (!atomic_load(&cancelled)) { // Decompress the image data (this may be CPU and memory intensive) UIImage *image = RCTDecodeImageWithData(data, size, scale, resizeMode); @@ -695,7 +704,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, }); return ^{ - OSAtomicOr32Barrier(1, &cancelled); + atomic_store(&cancelled, YES); }; } } diff --git a/Libraries/Image/RCTImageStoreManager.m b/Libraries/Image/RCTImageStoreManager.m index 9d89ca0f45f..690258e6522 100644 --- a/Libraries/Image/RCTImageStoreManager.m +++ b/Libraries/Image/RCTImageStoreManager.m @@ -9,7 +9,7 @@ #import "RCTImageStoreManager.h" -#import +#import #import #import @@ -137,14 +137,14 @@ RCT_EXPORT_METHOD(addImageFromBase64:(NSString *)base64String - (id)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate { - __block volatile uint32_t cancelled = 0; + __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); void (^cancellationBlock)(void) = ^{ - OSAtomicOr32Barrier(1, &cancelled); + atomic_store(&cancelled, YES); }; // Dispatch async to give caller time to cancel the request dispatch_async(_methodQueue, ^{ - if (cancelled) { + if (atomic_load(&cancelled)) { return; } diff --git a/Libraries/Image/RCTLocalAssetImageLoader.m b/Libraries/Image/RCTLocalAssetImageLoader.m index 17acd15b88c..7186f9aa59b 100644 --- a/Libraries/Image/RCTLocalAssetImageLoader.m +++ b/Libraries/Image/RCTLocalAssetImageLoader.m @@ -9,7 +9,7 @@ #import "RCTLocalAssetImageLoader.h" -#import +#import #import @@ -44,9 +44,9 @@ RCT_EXPORT_MODULE() partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler completionHandler:(RCTImageLoaderCompletionBlock)completionHandler { - __block volatile uint32_t cancelled = 0; + __block atomic_bool cancelled = ATOMIC_VAR_INIT(NO); RCTExecuteOnMainQueue(^{ - if (cancelled) { + if (atomic_load(&cancelled)) { return; } @@ -64,7 +64,7 @@ RCT_EXPORT_MODULE() }); return ^{ - OSAtomicOr32Barrier(1, &cancelled); + atomic_store(&cancelled, YES); }; }