Skip to content

Commit

Permalink
Synchronize RCTImageLoader loaders initialization
Browse files Browse the repository at this point in the history
Summary:
The method `imageURLLoaderForURL` can be called from multiple threads. This adds a mutex to make sure that _loaders is initialized with a non-nil value only once.

We'll only lock this mutex at one point in time as long as `_loadersProvider()` gives a value, so the mutex doesn't affect performance.

Changelog: [iOS][Fixed] Synchronize RCTImageLoader loaders initialization

Reviewed By: fkgozali

Differential Revision: D24513083

fbshipit-source-id: b89ef8a82729eda508162b01f7fdaa8a291f40d0
  • Loading branch information
p-sun authored and facebook-github-bot committed Oct 24, 2020
1 parent 0d1f93c commit edb6fa7
Showing 1 changed file with 22 additions and 18 deletions.
40 changes: 22 additions & 18 deletions Libraries/Image/RCTImageLoader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ @implementation RCTImageLoader
NSMutableArray *_pendingDecodes;
NSInteger _scheduledDecodes;
NSUInteger _activeBytes;
std::mutex _loadersMutex;
__weak id<RCTImageRedirectProtocol> _redirectDelegate;
}

Expand Down Expand Up @@ -184,26 +185,29 @@ - (void)setImageCache:(id<RCTImageCache>)cache
}

if (!_loaders) {
// Get loaders, sorted in reverse priority order (highest priority first)

if (_loadersProvider) {
_loaders = _loadersProvider();
} else {
RCTAssert(_bridge, @"Trying to find RCTImageURLLoaders and bridge not set.");
_loaders = [_bridge modulesConformingToProtocol:@protocol(RCTImageURLLoader)];
}

_loaders = [_loaders sortedArrayUsingComparator:^NSComparisonResult(id<RCTImageURLLoader> a, id<RCTImageURLLoader> b) {
float priorityA = [a respondsToSelector:@selector(loaderPriority)] ? [a loaderPriority] : 0;
float priorityB = [b respondsToSelector:@selector(loaderPriority)] ? [b loaderPriority] : 0;
if (priorityA > priorityB) {
return NSOrderedAscending;
} else if (priorityA < priorityB) {
return NSOrderedDescending;
std::unique_lock<std::mutex> guard(_loadersMutex);
if (!_loaders) {

// Get loaders, sorted in reverse priority order (highest priority first)
if (_loadersProvider) {
_loaders = _loadersProvider();
} else {
return NSOrderedSame;
RCTAssert(_bridge, @"Trying to find RCTImageURLLoaders and bridge not set.");
_loaders = [_bridge modulesConformingToProtocol:@protocol(RCTImageURLLoader)];
}
}];

_loaders = [_loaders sortedArrayUsingComparator:^NSComparisonResult(id<RCTImageURLLoader> a, id<RCTImageURLLoader> b) {
float priorityA = [a respondsToSelector:@selector(loaderPriority)] ? [a loaderPriority] : 0;
float priorityB = [b respondsToSelector:@selector(loaderPriority)] ? [b loaderPriority] : 0;
if (priorityA > priorityB) {
return NSOrderedAscending;
} else if (priorityA < priorityB) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
}
}

if (RCT_DEBUG) {
Expand Down

0 comments on commit edb6fa7

Please sign in to comment.