Skip to content

Commit 7fd5c02

Browse files
author
Mallory Paine
committed
Relinquish the image table lock while calling drawing block. Add new mechanism to synchronize on entry index to ensure only a single writer per index val.
1 parent e424c80 commit 7fd5c02

1 file changed

Lines changed: 37 additions & 14 deletions

File tree

FastImageCache/FICImageTable.m

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ @interface FICImageTable () {
5353
NSCountedSet *_chunkSet;
5454

5555
NSRecursiveLock *_lock;
56+
CFMutableDictionaryRef _indexNumbers;
5657

5758
// Image table metadata
5859
NSMutableDictionary *_indexMap; // Key: entity UUID, value: integer index into the table file
@@ -129,6 +130,8 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
129130
}
130131

131132
_lock = [[NSRecursiveLock alloc] init];
133+
_indexNumbers = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
134+
132135
_imageFormat = [imageFormat copy];
133136
_imageFormatDictionary = [imageFormat dictionaryRepresentation];
134137

@@ -268,16 +271,6 @@ - (void)setEntryForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *
268271
// Create context whose backing store *is* the mapped file data
269272
FICImageTableEntry *entryData = [self _entryDataAtIndex:newEntryIndex];
270273
if (entryData) {
271-
CGContextRef context = CGBitmapContextCreate([entryData bytes], pixelSize.width, pixelSize.height, bitsPerComponent, _imageRowLength, colorSpace, bitmapInfo);
272-
CGColorSpaceRelease(colorSpace);
273-
274-
CGContextTranslateCTM(context, 0, pixelSize.height);
275-
CGContextScaleCTM(context, _screenScale, -_screenScale);
276-
277-
// Call drawing block to allow client to draw into the context
278-
imageDrawingBlock(context, [_imageFormat imageSize]);
279-
CGContextRelease(context);
280-
281274
[entryData setEntityUUIDBytes:FICUUIDBytesWithString(entityUUID)];
282275
[entryData setSourceImageUUIDBytes:FICUUIDBytesWithString(sourceImageUUID)];
283276

@@ -290,12 +283,32 @@ - (void)setEntryForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *
290283
[self _entryWasAccessedWithEntityUUID:entityUUID];
291284
[self saveMetadata];
292285

293-
// Write the data back to the filesystem
294-
[entryData flush];
286+
// Unique, unchanging pointer for this entry's index
287+
NSNumber *indexNumber = [self _numberForEntryAtIndex:newEntryIndex];
288+
289+
// Relinquish the image table lock before calling potentially slow imageDrawingBlock to unblock other FIC operations
290+
[_lock unlock];
291+
292+
CGContextRef context = CGBitmapContextCreate([entryData bytes], pixelSize.width, pixelSize.height, bitsPerComponent, _imageRowLength, colorSpace, bitmapInfo);
293+
CGColorSpaceRelease(colorSpace);
294+
295+
CGContextTranslateCTM(context, 0, pixelSize.height);
296+
CGContextScaleCTM(context, _screenScale, -_screenScale);
297+
298+
@synchronized(indexNumber) {
299+
// Call drawing block to allow client to draw into the context
300+
imageDrawingBlock(context, [_imageFormat imageSize]);
301+
CGContextRelease(context);
302+
303+
// Write the data back to the filesystem
304+
[entryData flush];
305+
}
306+
} else {
307+
[_lock unlock];
295308
}
309+
} else {
310+
[_lock unlock];
296311
}
297-
298-
[_lock unlock];
299312
}
300313
}
301314

@@ -564,6 +577,16 @@ - (void)_entryWasAccessedWithEntityUUID:(NSString *)entityUUID {
564577
}
565578
}
566579

580+
// Unchanging pointer value for a given entry index to synchronize on
581+
- (NSNumber *)_numberForEntryAtIndex:(NSInteger)index {
582+
NSNumber *resultNumber = (__bridge id)CFDictionaryGetValue(_indexNumbers, (const void *)index);
583+
if (!resultNumber) {
584+
resultNumber = [NSNumber numberWithInteger:index];
585+
CFDictionarySetValue(_indexNumbers, (const void *)index, (__bridge void *)resultNumber);
586+
}
587+
return resultNumber;
588+
}
589+
567590
#pragma mark - Working with Metadata
568591

569592
- (void)saveMetadata {

0 commit comments

Comments
 (0)