Repository navigation
Expand file tree
/
Copy pathDMMemoize.h
More file actions
48 lines (43 loc) · 1.95 KB
/
Copy pathDMMemoize.h
File metadata and controls
48 lines (43 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//
// DMMemoize.h
// DMMemoize
//
// Created by Jonathon Mah on 2012-11-10.
// Copyright (c) 2012 Delicious Monster Software. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface DMMemoize : NSObject
/* Helper to add return value caching to pure methods (those without side-effects).
*
* Example.
* The following function calculates the return value every time:
*
* - (id)someFunctionOf:(id)key {
* return [self expensiveCalculationWith:key];
* }
*
* Using DMMemoize so each value is only calculated once:
*
* - (id)someFunctionOf:(id)key {
* static char cacheToken;
* return [DMMemoize cachedValueForKey:key storageOwner:self token:&cacheToken generator:^{
* return [self expensiveCalculationWith:key];
* }];
* }
*
* The `cacheKey` and return values can be any object (including NSNull), or nil.
*
* The cache keys and return values will be retained until the storage owner is deallocated.
*
* If the pure method takes multiple parameters, combine them all into a single object to be used as cacheKey.
* Although NSArray and NSDictionary are obvious candidates for this (e.g. +cachedValueForKey:@[arg1, arg2] …),
* they are poor choices due to the default -hash of those objects being their count. This will typically lead
* to 100% hash collisions, so cache lookup will be linear instead of constant. It's much better to use a
* container with a hash that's a function of its elements' hashes. A composite string can serve this purpose
* (e.g. [NSString stringWithFormat:@"%@ %@", arg1, arg2]), though of course be careful to avoid ambiguous
* situations (i.e. for the above example, key=@"A B C" is the same for [@"A B", @"C"] and [@"A", @"B C"]).
*
* This code is thread-safe. The generator block will be called exactly once per cacheKey.
*/
+ (id)cachedValueForKey:(id)cacheKey storageOwner:(id)cacheOwner token:(void *)staticToken generator:(id(^)(void))generatorBlock __attribute__((nonnull(2,3,4)));
@end