Skip to content

Commit

Permalink
setup test to use custom queue for RCTImageStoreManager operations in…
Browse files Browse the repository at this point in the history
…stead of module queue

Summary:
Changelog: [Internal]

in my quest to get rid of all synthesized `methodQueue`s, we have `RCTImageStoreManager` which uses this throughout. in this diff, i add a config that uses a queue that is managed by the module itself instead of the one generated by the infra.

Reviewed By: cipolleschi

Differential Revision: D50585904
  • Loading branch information
philIip authored and facebook-github-bot committed Oct 24, 2023
1 parent b5dae01 commit d2a2baf
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 10 deletions.
2 changes: 2 additions & 0 deletions packages/react-native/Libraries/Image/RCTImageStoreManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#import <React/RCTBridgeProxy.h>
#import <React/RCTURLRequestHandler.h>

RCT_EXTERN void RCTEnableImageStoreManagerStorageQueue(BOOL enabled);

@interface RCTImageStoreManager : NSObject <RCTURLRequestHandler>

/**
Expand Down
47 changes: 37 additions & 10 deletions packages/react-native/Libraries/Image/RCTImageStoreManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,54 @@
#import "RCTImagePlugins.h"

static NSString *const RCTImageStoreURLScheme = @"rct-image-store";
static BOOL gImageStoreManagerStorageQueueEnabled = NO;

void RCTEnableImageStoreManagerStorageQueue(BOOL enabled)
{
gImageStoreManagerStorageQueueEnabled = enabled;
}

@interface RCTImageStoreManager () <NativeImageStoreIOSSpec>
@end

@implementation RCTImageStoreManager {
NSMutableDictionary<NSString *, NSData *> *_store;
NSUInteger _id;
dispatch_queue_t _storageQueue;
}

@synthesize methodQueue = _methodQueue;

RCT_EXPORT_MODULE()

+ (BOOL)requiresMainQueueSetup
{
return NO;
}

- (instancetype)init
{
if (self = [super init]) {
if (gImageStoreManagerStorageQueueEnabled) {
_storageQueue = dispatch_queue_create("com.facebook.react.imagestoremanager.storage", DISPATCH_QUEUE_SERIAL);
}
}
return self;
}

- (dispatch_queue_t)_getAsyncQueue
{
return gImageStoreManagerStorageQueueEnabled ? _storageQueue : _methodQueue;
}

- (float)handlerPriority
{
return 1;
}

- (void)removeImageForTag:(NSString *)imageTag withBlock:(void (^)(void))block
{
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
[self removeImageForTag:imageTag];
if (block) {
block();
Expand All @@ -51,7 +78,7 @@ - (void)removeImageForTag:(NSString *)imageTag withBlock:(void (^)(void))block

- (NSString *)_storeImageData:(NSData *)imageData
{
RCTAssertThread(_methodQueue, @"Must be called on RCTImageStoreManager thread");
RCTAssertThread([self _getAsyncQueue], @"Must be called on RCTImageStoreManager thread");

if (!_store) {
_store = [NSMutableDictionary new];
Expand All @@ -66,23 +93,23 @@ - (NSString *)_storeImageData:(NSData *)imageData
- (void)storeImageData:(NSData *)imageData withBlock:(void (^)(NSString *imageTag))block
{
RCTAssertParam(block);
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
block([self _storeImageData:imageData]);
});
}

- (void)getImageDataForTag:(NSString *)imageTag withBlock:(void (^)(NSData *imageData))block
{
RCTAssertParam(block);
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
block(self->_store[imageTag]);
});
}

- (void)storeImage:(UIImage *)image withBlock:(void (^)(NSString *imageTag))block
{
RCTAssertParam(block);
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
NSString *imageTag = [self _storeImageData:RCTGetImageData(image, 0.75)];
dispatch_async(dispatch_get_main_queue(), ^{
block(imageTag);
Expand Down Expand Up @@ -128,7 +155,7 @@ - (void)storeImage:(UIImage *)image withBlock:(void (^)(NSString *imageTag))bloc
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
if (imageData) {
dispatch_async(self->_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
successCallback(@[ [self _storeImageData:imageData] ]);
});
} else {
Expand All @@ -152,7 +179,7 @@ - (id)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate
};

// Dispatch async to give caller time to cancel the request
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
if (cancelled->load()) {
return;
}
Expand Down Expand Up @@ -213,7 +240,7 @@ - (NSString *)storeImage:(UIImage *)image
RCTLogWarn(
@"RCTImageStoreManager.storeImage() is deprecated and has poor performance. Use an alternative method instead.");
__block NSString *imageTag;
dispatch_sync(_methodQueue, ^{
dispatch_sync([self _getAsyncQueue], ^{
imageTag = [self _storeImageData:RCTGetImageData(image, 0.75)];
});
return imageTag;
Expand All @@ -225,7 +252,7 @@ - (UIImage *)imageForTag:(NSString *)imageTag
RCTLogWarn(
@"RCTImageStoreManager.imageForTag() is deprecated and has poor performance. Use an alternative method instead.");
__block NSData *imageData;
dispatch_sync(_methodQueue, ^{
dispatch_sync([self _getAsyncQueue], ^{
imageData = self->_store[imageTag];
});
return [UIImage imageWithData:imageData];
Expand All @@ -234,7 +261,7 @@ - (UIImage *)imageForTag:(NSString *)imageTag
- (void)getImageForTag:(NSString *)imageTag withBlock:(void (^)(UIImage *image))block
{
RCTAssertParam(block);
dispatch_async(_methodQueue, ^{
dispatch_async([self _getAsyncQueue], ^{
NSData *imageData = self->_store[imageTag];
dispatch_async(dispatch_get_main_queue(), ^{
// imageWithData: is not thread-safe, so we can't do this on methodQueue
Expand Down

0 comments on commit d2a2baf

Please sign in to comment.