summaryrefslogtreecommitdiff
path: root/platform/ios/MGLFileCache.mm
blob: 3303b395f970c31d24c66e7d9ecf5b85864a6ad4 (plain)
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#import "MGLFileCache.h"

@interface MGLFileCache ()

@property (nonatomic) MGLFileCache *sharedInstance;
@property (nonatomic) mbgl::SQLiteCache *sharedCache;
@property (nonatomic) NSHashTable *retainers;

@end

@implementation MGLFileCache

const std::string &defaultCacheDatabasePath() {
    static const std::string path = []() -> std::string {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        if ([paths count] == 0) {
            // Disable the cache if we don't have a location to write.
            return "";
        }

        NSString *libraryDirectory = [paths objectAtIndex:0];
        return [[libraryDirectory stringByAppendingPathComponent:@"cache.db"] UTF8String];
    }();
    return path;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _retainers = [NSHashTable weakObjectsHashTable];
    }
    return self;
}

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static MGLFileCache *_sharedInstance;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}

- (void)teardown {
    if (self.sharedCache) {
        delete self.sharedCache;
        self.sharedCache = nullptr;
    }
}

- (void)dealloc {
    [self.retainers removeAllObjects];
    [self teardown];
}

+ (mbgl::SQLiteCache *)obtainSharedCacheWithObject:(NSObject *)object {
    return [[MGLFileCache sharedInstance] obtainSharedCacheWithObject:object];
}

- (mbgl::SQLiteCache *)obtainSharedCacheWithObject:(NSObject *)object {
    assert([[NSThread currentThread] isMainThread]);
    if (!self.sharedCache) {
        self.sharedCache = new mbgl::SQLiteCache(defaultCacheDatabasePath());
    }
    [self.retainers addObject:object];
    return self.sharedCache;
}

+ (void)releaseSharedCacheForObject:(NSObject *)object {
    return [[MGLFileCache sharedInstance] releaseSharedCacheForObject:object];
}

- (void)releaseSharedCacheForObject:(NSObject *)object {
    assert([[NSThread currentThread] isMainThread]);
    if ([self.retainers containsObject:object]) {
        [self.retainers removeObject:object];
    }
    if ([self.retainers count] == 0) {
        [self teardown];
    }
}

@end