Skip to content

Commit 9a44792

Browse files
author
Mallory Paine
committed
Take #2: Attempt to fix unreproducible crasher. Don't rely on auto-zeroing weak references to know when it's no longer OK to hand back a cached value.
1 parent 4c5e2dc commit 9a44792

6 files changed

Lines changed: 29 additions & 73 deletions

File tree

FastImageCache/FICImageTable.m

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#import "FICImageTableChunk.h"
1313
#import "FICImageTableEntry.h"
1414
#import "FICUtilities.h"
15-
#import "FICWeakReference.h"
1615

1716
#import "FICImageCache+FICErrorLogging.h"
1817

@@ -51,7 +50,8 @@ @interface FICImageTable () {
5150
NSInteger _chunkCount;
5251

5352
NSMutableDictionary *_chunkDictionary;
54-
NSMutableArray *_recentChunks;
53+
NSCountedSet *_chunkSet;
54+
5555
NSRecursiveLock *_lock;
5656

5757
// Image table metadata
@@ -140,6 +140,7 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
140140
_imageLength = _imageRowLength * (NSInteger)pixelSize.height;
141141

142142
_chunkDictionary = [[NSMutableDictionary alloc] init];
143+
_chunkSet = [[NSCountedSet alloc] init];
143144

144145
_indexMap = [[NSMutableDictionary alloc] init];
145146
_occupiedIndexes = [[NSMutableIndexSet alloc] init];
@@ -149,8 +150,6 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
149150

150151
_sourceImageMap = [[NSMutableDictionary alloc] init];
151152

152-
_recentChunks = [[NSMutableArray alloc] init];
153-
154153
_filePath = [[self tableFilePath] copy];
155154

156155
[self _loadMetadata];
@@ -206,24 +205,13 @@ - (void)dealloc {
206205
#pragma mark - Working with Chunks
207206

208207
- (FICImageTableChunk *)_cachedChunkAtIndex:(NSInteger)index {
209-
FICImageTableChunk *cachedChunk = nil;
210-
NSNumber *indexNumber = @(index);
211-
FICWeakReference *chunkReference = [_chunkDictionary objectForKey:indexNumber];
212-
213-
if (chunkReference) {
214-
cachedChunk = [chunkReference object];
215-
if (!cachedChunk) {
216-
[_chunkDictionary removeObjectForKey:indexNumber];
217-
}
218-
}
219-
220-
return cachedChunk;
208+
return [_chunkDictionary objectForKey:@(index)];
221209
}
222210

223211
- (void)_setChunk:(FICImageTableChunk *)chunk index:(NSInteger)index {
224212
NSNumber *indexNumber = @(index);
225213
if (chunk != nil) {
226-
[_chunkDictionary setObject:[[FICWeakReference alloc] initWithObject:chunk] forKey:indexNumber];
214+
[_chunkDictionary setObject:chunk forKey:indexNumber];
227215
} else {
228216
[_chunkDictionary removeObjectForKey:indexNumber];
229217
}
@@ -245,15 +233,6 @@ - (FICImageTableChunk *)_chunkAtIndex:(NSInteger)index {
245233
chunk = [[FICImageTableChunk alloc] initWithFileDescriptor:_fileDescriptor index:index length:chunkLength];
246234
[self _setChunk:chunk index:index];
247235
}
248-
249-
if (chunk != nil) {
250-
static const NSInteger __recentChunksToKeepMapped = 2;
251-
[_recentChunks insertObject:chunk atIndex:0];
252-
253-
if ([_recentChunks count] > __recentChunksToKeepMapped) {
254-
[_recentChunks removeLastObject];
255-
}
256-
}
257236
}
258237

259238
return chunk;
@@ -467,6 +446,13 @@ - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index {
467446
void *mappedChunkAddress = [chunk bytes];
468447
void *mappedEntryAddress = mappedChunkAddress + entryOffsetInChunk;
469448
entryData = [[FICImageTableEntry alloc] initWithImageTableChunk:chunk bytes:mappedEntryAddress length:_entryLength];
449+
450+
[_chunkSet addObject:chunk];
451+
452+
__weak FICImageTable *weakSelf = self;
453+
[entryData executeBlockOnDealloc:^{
454+
[weakSelf _entryWasDeallocatedFromChunk:chunk];
455+
}];
470456
}
471457
}
472458

@@ -475,6 +461,15 @@ - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index {
475461
return entryData;
476462
}
477463

464+
- (void)_entryWasDeallocatedFromChunk:(FICImageTableChunk *)chunk {
465+
[_lock lock];
466+
[_chunkSet removeObject:chunk];
467+
if ([_chunkSet countForObject:chunk] == 0) {
468+
[self _setChunk:nil index:[chunk index]];
469+
}
470+
[_lock unlock];
471+
}
472+
478473
- (NSInteger)_nextEntryIndex {
479474
NSMutableIndexSet *unoccupiedIndexes = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _entryCount)];
480475
[unoccupiedIndexes removeIndexes:_occupiedIndexes];

FastImageCache/FICImageTableEntry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ typedef struct {
5252
*/
5353
@property (nonatomic, assign) CFUUIDBytes sourceImageUUIDBytes;
5454

55+
@property (nonatomic, readonly) FICImageTableChunk *imageTableChunk;
56+
5557
///----------------------------------------
5658
/// @name Initializing an Image Table Entry
5759
///----------------------------------------

FastImageCache/FICImageTableEntry.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ @interface FICImageTableEntry () {
2121
FICImageTableChunk *_imageTableChunk;
2222
void *_bytes;
2323
size_t _length;
24-
dispatch_block_t _deallocBlock;
24+
NSMutableArray *_deallocBlocks;
2525
}
2626

2727
@end
@@ -32,6 +32,7 @@ @implementation FICImageTableEntry
3232

3333
@synthesize bytes = _bytes;
3434
@synthesize length = _length;
35+
@synthesize imageTableChunk = _imageTableChunk;
3536

3637
#pragma mark - Property Accessors
3738

@@ -64,18 +65,19 @@ - (id)initWithImageTableChunk:(FICImageTableChunk *)imageTableChunk bytes:(void
6465
_imageTableChunk = imageTableChunk;
6566
_bytes = bytes;
6667
_length = length;
68+
_deallocBlocks = [[NSMutableArray alloc] init];
6769
}
6870

6971
return self;
7072
}
7173

7274
- (void)executeBlockOnDealloc:(dispatch_block_t)block {
73-
_deallocBlock = [block copy];
75+
[_deallocBlocks addObject:[block copy]];
7476
}
7577

7678
- (void)dealloc {
77-
if (_deallocBlock) {
78-
_deallocBlock();
79+
for (dispatch_block_t block in _deallocBlocks) {
80+
block();
7981
}
8082
}
8183

FastImageCache/FICWeakReference.h

Lines changed: 0 additions & 17 deletions
This file was deleted.

FastImageCache/FICWeakReference.m

Lines changed: 0 additions & 20 deletions
This file was deleted.

FastImageCacheDemo/FastImageCacheDemo.xcodeproj/project.pbxproj

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
2E1BC90117C57CDF00836A7E /* FICDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E1BC8FD17C57CD300836A7E /* FICDViewController.m */; };
2121
2E64541017FF24C0001D0531 /* FICDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E64540F17FF24C0001D0531 /* FICDTableView.m */; };
2222
2EA7994417B2A10200684B86 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA7993F17B2A10200684B86 /* main.m */; };
23-
31F9BA0418822719009630D0 /* FICWeakReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 31F9BA0318822719009630D0 /* FICWeakReference.m */; };
2423
EB171332181F089F00EB0E24 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB171331181F089F00EB0E24 /* CoreImage.framework */; };
2524
EB642D8017DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m in Sources */ = {isa = PBXBuildFile; fileRef = EB642D7F17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.m */; };
2625
EB6BD53818079DAB00D762CE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB6BD53718079DAB00D762CE /* CoreGraphics.framework */; };
@@ -57,8 +56,6 @@
5756
2E64540E17FF24C0001D0531 /* FICDTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDTableView.h; sourceTree = "<group>"; };
5857
2E64540F17FF24C0001D0531 /* FICDTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICDTableView.m; sourceTree = "<group>"; };
5958
2EA7993F17B2A10200684B86 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
60-
31F9BA0218822719009630D0 /* FICWeakReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICWeakReference.h; sourceTree = "<group>"; };
61-
31F9BA0318822719009630D0 /* FICWeakReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FICWeakReference.m; sourceTree = "<group>"; };
6259
EB171331181F089F00EB0E24 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
6360
EB642D3717DC9C690013D644 /* FastImageCacheDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "FastImageCacheDemo-Info.plist"; sourceTree = "<group>"; };
6461
EB642D7E17DCB1750013D644 /* FICDFullscreenPhotoDisplayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FICDFullscreenPhotoDisplayController.h; sourceTree = "<group>"; };
@@ -148,8 +145,6 @@
148145
EB6BD53918079E2D00D762CE /* FICImports.h */,
149146
2E1BC8ED17C57C4700836A7E /* FICUtilities.h */,
150147
2E1BC8EE17C57C4700836A7E /* FICUtilities.m */,
151-
31F9BA0218822719009630D0 /* FICWeakReference.h */,
152-
31F9BA0318822719009630D0 /* FICWeakReference.m */,
153148
);
154149
name = FastImageCache;
155150
path = ../FastImageCache;
@@ -248,7 +243,6 @@
248243
isa = PBXSourcesBuildPhase;
249244
buildActionMask = 2147483647;
250245
files = (
251-
31F9BA0418822719009630D0 /* FICWeakReference.m in Sources */,
252246
2EA7994417B2A10200684B86 /* main.m in Sources */,
253247
2E1BC8F017C57C4700836A7E /* FICImageCache.m in Sources */,
254248
2E1BC8F117C57C4700836A7E /* FICImageFormat.m in Sources */,

0 commit comments

Comments
 (0)