Skip to content

Commit 8ab84a3

Browse files
committed
Introduce the concept of in use entries.
Entries that are in use are immune from eviction. This concept is needed to protect the bits that are currently being referenced by a UIImage/CGImageRef from being overwritten. Note also that inUse is a refcounted concept since multiple FICImageTableEntry's can be allocated against the same entityUUID/bits in the backing file. A side effect of this change is that the imageFormat's maximumCount is no longer a hard limit since it is possible that all maximumCount entries could be in use.
1 parent f3aad3f commit 8ab84a3

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

FastImageCache/FICImageTable.m

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ @interface FICImageTable () {
5858
NSMutableDictionary *_sourceImageMap; // Key: entity UUID, value: source image UUID
5959
NSMutableIndexSet *_occupiedIndexes;
6060
NSMutableArray *_MRUEntries;
61+
NSCountedSet *_inUseEntries;
6162
NSDictionary *_imageFormatDictionary;
6263
}
6364

@@ -143,6 +144,7 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
143144
_occupiedIndexes = [[NSMutableIndexSet alloc] init];
144145

145146
_MRUEntries = [[NSMutableArray alloc] init];
147+
_inUseEntries = [NSCountedSet set];
146148
_sourceImageMap = [[NSMutableDictionary alloc] init];
147149

148150
_recentChunks = [[NSMutableArray alloc] init];
@@ -256,8 +258,7 @@ - (void)setEntryForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *
256258
newEntryIndex = [self _nextEntryIndex];
257259

258260
if (newEntryIndex >= _entryCount) {
259-
NSInteger maximumEntryCount = [_imageFormat maximumCount];
260-
NSInteger newEntryCount = MIN(maximumEntryCount, _entryCount + MAX(_entriesPerChunk, newEntryIndex - _entryCount + 1));
261+
NSInteger newEntryCount = _entryCount + MAX(_entriesPerChunk, newEntryIndex - _entryCount + 1);
261262
[self _setEntryCount:newEntryCount];
262263
}
263264
}
@@ -459,13 +460,33 @@ - (NSInteger)_nextEntryIndex {
459460

460461
if (index >= [self _maximumCount] && [_MRUEntries count]) {
461462
// Evict the oldest/least-recently accessed entry here
462-
[self deleteEntryForEntityUUID:[_MRUEntries lastObject]];
463+
464+
NSString *oldestEvictableEntityUUID = [self oldestEvictableEntityUUID];
465+
if (oldestEvictableEntityUUID) {
466+
[self deleteEntryForEntityUUID:oldestEvictableEntityUUID];
463467
index = [self _nextEntryIndex];
464468
}
469+
}
470+
471+
if (index >= [self _maximumCount]) {
472+
NSString *message = [NSString stringWithFormat:@"FICImageTable - unable to evict entry from table '%@' to make room. New index %d, desired max %d", [_imageFormat name], index, [self _maximumCount]];
473+
[[FICImageCache sharedImageCache] _logMessage:message];
474+
}
465475

466476
return index;
467477
}
468478

479+
- (NSString *)oldestEvictableEntityUUID {
480+
for (uint i = _MRUEntries.count - 1; i; i--) {
481+
NSString *candidateUUID = [_MRUEntries objectAtIndex:i];
482+
if (![_inUseEntries containsObject:candidateUUID]) {
483+
return candidateUUID;
484+
}
485+
}
486+
487+
return nil;
488+
}
489+
469490
- (NSInteger)_indexOfEntryForEntityUUID:(NSString *)entityUUID {
470491
NSInteger index = NSNotFound;
471492
if (_indexMap != nil && entityUUID != nil) {
@@ -560,6 +581,7 @@ - (void)reset {
560581

561582
[_indexMap removeAllObjects];
562583
[_occupiedIndexes removeAllIndexes];
584+
[_inUseEntries removeAllObjects];
563585
[_MRUEntries removeAllObjects];
564586
[_sourceImageMap removeAllObjects];
565587

0 commit comments

Comments
 (0)