Skip to content

Commit 1e7ff51

Browse files
author
Mallory Paine
committed
Synchronize on entry's index when reading an image as well. This way, we'll wait for a write to finish if it's occurring on background thread.
1 parent c207e95 commit 1e7ff51

3 files changed

Lines changed: 43 additions & 35 deletions

File tree

FastImageCache/FICImageTable.m

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -325,42 +325,45 @@ - (UIImage *)newImageForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSStr
325325
BOOL entityUUIDIsCorrect = entityUUID == nil || [entityUUID isEqualToString:entryEntityUUID];
326326
BOOL sourceImageUUIDIsCorrect = sourceImageUUID == nil || [sourceImageUUID isEqualToString:entrySourceImageUUID];
327327

328-
if (entityUUIDIsCorrect == NO || sourceImageUUIDIsCorrect == NO) {
329-
// The UUIDs don't match, so we need to invalidate the entry.
330-
[self deleteEntryForEntityUUID:entityUUID];
331-
[self saveMetadata];
332-
} else {
333-
[self _entryWasAccessedWithEntityUUID:entityUUID];
334-
335-
// Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.
336-
CGDataProviderRef dataProvider = CGDataProviderCreateWithData((__bridge_retained void *)entryData, [entryData bytes], [entryData imageLength], _FICReleaseImageData);
337-
338-
[_inUseEntries addObject:entityUUID];
339-
__weak FICImageTable *weakSelf = self;
340-
[entryData executeBlockOnDealloc:^{
341-
[weakSelf removeInUseForEntityUUID:entityUUID];
342-
}];
343-
344-
CGSize pixelSize = [_imageFormat pixelSize];
345-
CGBitmapInfo bitmapInfo = [_imageFormat bitmapInfo];
346-
NSInteger bitsPerComponent = [_imageFormat bitsPerComponent];
347-
NSInteger bitsPerPixel = [_imageFormat bytesPerPixel] * 8;
348-
CGColorSpaceRef colorSpace = [_imageFormat isGrayscale] ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
349-
350-
CGImageRef imageRef = CGImageCreate(pixelSize.width, pixelSize.height, bitsPerComponent, bitsPerPixel, _imageRowLength, colorSpace, bitmapInfo, dataProvider, NULL, false, (CGColorRenderingIntent)0);
351-
CGDataProviderRelease(dataProvider);
352-
CGColorSpaceRelease(colorSpace);
353-
354-
if (imageRef != NULL) {
355-
image = [[UIImage alloc] initWithCGImage:imageRef scale:_screenScale orientation:UIImageOrientationUp];
356-
CGImageRelease(imageRef);
328+
NSNumber *indexNumber = [self _numberForEntryAtIndex:[entryData index]];
329+
@synchronized(indexNumber) {
330+
if (entityUUIDIsCorrect == NO || sourceImageUUIDIsCorrect == NO) {
331+
// The UUIDs don't match, so we need to invalidate the entry.
332+
[self deleteEntryForEntityUUID:entityUUID];
333+
[self saveMetadata];
357334
} else {
358-
NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s could not create a new CGImageRef for entity UUID %@.", __PRETTY_FUNCTION__, entityUUID];
359-
[[FICImageCache sharedImageCache] _logMessage:message];
360-
}
361-
362-
if (image != nil && preheatData) {
363-
[entryData preheat];
335+
[self _entryWasAccessedWithEntityUUID:entityUUID];
336+
337+
// Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.
338+
CGDataProviderRef dataProvider = CGDataProviderCreateWithData((__bridge_retained void *)entryData, [entryData bytes], [entryData imageLength], _FICReleaseImageData);
339+
340+
[_inUseEntries addObject:entityUUID];
341+
__weak FICImageTable *weakSelf = self;
342+
[entryData executeBlockOnDealloc:^{
343+
[weakSelf removeInUseForEntityUUID:entityUUID];
344+
}];
345+
346+
CGSize pixelSize = [_imageFormat pixelSize];
347+
CGBitmapInfo bitmapInfo = [_imageFormat bitmapInfo];
348+
NSInteger bitsPerComponent = [_imageFormat bitsPerComponent];
349+
NSInteger bitsPerPixel = [_imageFormat bytesPerPixel] * 8;
350+
CGColorSpaceRef colorSpace = [_imageFormat isGrayscale] ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
351+
352+
CGImageRef imageRef = CGImageCreate(pixelSize.width, pixelSize.height, bitsPerComponent, bitsPerPixel, _imageRowLength, colorSpace, bitmapInfo, dataProvider, NULL, false, (CGColorRenderingIntent)0);
353+
CGDataProviderRelease(dataProvider);
354+
CGColorSpaceRelease(colorSpace);
355+
356+
if (imageRef != NULL) {
357+
image = [[UIImage alloc] initWithCGImage:imageRef scale:_screenScale orientation:UIImageOrientationUp];
358+
CGImageRelease(imageRef);
359+
} else {
360+
NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s could not create a new CGImageRef for entity UUID %@.", __PRETTY_FUNCTION__, entityUUID];
361+
[[FICImageCache sharedImageCache] _logMessage:message];
362+
}
363+
364+
if (image != nil && preheatData) {
365+
[entryData preheat];
366+
}
364367
}
365368
}
366369
}
@@ -470,6 +473,7 @@ - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index {
470473
void *mappedChunkAddress = [chunk bytes];
471474
void *mappedEntryAddress = mappedChunkAddress + entryOffsetInChunk;
472475
entryData = [[FICImageTableEntry alloc] initWithImageTableChunk:chunk bytes:mappedEntryAddress length:_entryLength];
476+
[entryData setIndex:index];
473477

474478
[_chunkSet addObject:chunk];
475479

FastImageCache/FICImageTableEntry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ typedef struct {
5454

5555
@property (nonatomic, readonly) FICImageTableChunk *imageTableChunk;
5656

57+
@property (nonatomic, assign) NSInteger index;
58+
5759
- (void)preheat;
5860

5961
///----------------------------------------

FastImageCache/FICImageTableEntry.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ @interface FICImageTableEntry () {
2222
void *_bytes;
2323
size_t _length;
2424
NSMutableArray *_deallocBlocks;
25+
NSInteger _index;
2526
}
2627

2728
@end
@@ -33,6 +34,7 @@ @implementation FICImageTableEntry
3334
@synthesize bytes = _bytes;
3435
@synthesize length = _length;
3536
@synthesize imageTableChunk = _imageTableChunk;
37+
@synthesize index = _index;
3638

3739
#pragma mark - Property Accessors
3840

0 commit comments

Comments
 (0)