123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- #import "TMCache.h"
- NSString * const TMCachePrefix = @"com.tumblr.TMCache";
- NSString * const TMCacheSharedName = @"TMCacheShared";
- @interface TMCache ()
- #if OS_OBJECT_USE_OBJC
- @property (strong, nonatomic) dispatch_queue_t queue;
- #else
- @property (assign, nonatomic) dispatch_queue_t queue;
- #endif
- @end
- @implementation TMCache
- #pragma mark - Initialization -
- #if !OS_OBJECT_USE_OBJC
- - (void)dealloc
- {
- dispatch_release(_queue);
- _queue = nil;
- }
- #endif
- - (instancetype)initWithName:(NSString *)name
- {
- return [self initWithName:name rootPath:[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
- }
- - (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath
- {
- if (!name)
- return nil;
- if (self = [super init]) {
- _name = [name copy];
-
- NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", TMCachePrefix, self];
- _queue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
- _diskCache = [[TMDiskCache alloc] initWithName:_name rootPath:rootPath];
- _memoryCache = [[TMMemoryCache alloc] init];
- }
- return self;
- }
- - (NSString *)description
- {
- return [[NSString alloc] initWithFormat:@"%@.%@.%p", TMCachePrefix, _name, self];
- }
- + (instancetype)sharedCache
- {
- static id cache;
- static dispatch_once_t predicate;
- dispatch_once(&predicate, ^{
- cache = [[self alloc] initWithName:TMCacheSharedName];
- });
- return cache;
- }
- #pragma mark - Public Asynchronous Methods -
- - (void)objectForKey:(NSString *)key block:(TMCacheObjectBlock)block
- {
- if (!key || !block)
- return;
- __weak TMCache *weakSelf = self;
- dispatch_async(_queue, ^{
- TMCache *strongSelf = weakSelf;
- if (!strongSelf)
- return;
- __weak TMCache *weakSelf = strongSelf;
-
- [strongSelf->_memoryCache objectForKey:key block:^(TMMemoryCache *cache, NSString *key, id object) {
- TMCache *strongSelf = weakSelf;
- if (!strongSelf)
- return;
-
- if (object) {
- [strongSelf->_diskCache fileURLForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
- // update the access time on disk
- }];
- __weak TMCache *weakSelf = strongSelf;
-
- dispatch_async(strongSelf->_queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf, key, object);
- });
- } else {
- __weak TMCache *weakSelf = strongSelf;
- [strongSelf->_diskCache objectForKey:key block:^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
- TMCache *strongSelf = weakSelf;
- if (!strongSelf)
- return;
-
- [strongSelf->_memoryCache setObject:object forKey:key block:nil];
-
- __weak TMCache *weakSelf = strongSelf;
-
- dispatch_async(strongSelf->_queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf, key, object);
- });
- }];
- }
- }];
- });
- }
- - (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(TMCacheObjectBlock)block
- {
- if (!key || !object)
- return;
- dispatch_group_t group = nil;
- TMMemoryCacheObjectBlock memBlock = nil;
- TMDiskCacheObjectBlock diskBlock = nil;
-
- if (block) {
- group = dispatch_group_create();
- dispatch_group_enter(group);
- dispatch_group_enter(group);
-
- memBlock = ^(TMMemoryCache *cache, NSString *key, id object) {
- dispatch_group_leave(group);
- };
-
- diskBlock = ^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
- dispatch_group_leave(group);
- };
- }
-
- [_memoryCache setObject:object forKey:key block:memBlock];
- [_diskCache setObject:object forKey:key block:diskBlock];
-
- if (group) {
- __weak TMCache *weakSelf = self;
- dispatch_group_notify(group, _queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf, key, object);
- });
-
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(group);
- #endif
- }
- }
- - (void)removeObjectForKey:(NSString *)key block:(TMCacheObjectBlock)block
- {
- if (!key)
- return;
-
- dispatch_group_t group = nil;
- TMMemoryCacheObjectBlock memBlock = nil;
- TMDiskCacheObjectBlock diskBlock = nil;
-
- if (block) {
- group = dispatch_group_create();
- dispatch_group_enter(group);
- dispatch_group_enter(group);
-
- memBlock = ^(TMMemoryCache *cache, NSString *key, id object) {
- dispatch_group_leave(group);
- };
-
- diskBlock = ^(TMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL) {
- dispatch_group_leave(group);
- };
- }
- [_memoryCache removeObjectForKey:key block:memBlock];
- [_diskCache removeObjectForKey:key block:diskBlock];
-
- if (group) {
- __weak TMCache *weakSelf = self;
- dispatch_group_notify(group, _queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf, key, nil);
- });
-
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(group);
- #endif
- }
- }
- - (void)removeAllObjects:(TMCacheBlock)block
- {
- dispatch_group_t group = nil;
- TMMemoryCacheBlock memBlock = nil;
- TMDiskCacheBlock diskBlock = nil;
-
- if (block) {
- group = dispatch_group_create();
- dispatch_group_enter(group);
- dispatch_group_enter(group);
-
- memBlock = ^(TMMemoryCache *cache) {
- dispatch_group_leave(group);
- };
-
- diskBlock = ^(TMDiskCache *cache) {
- dispatch_group_leave(group);
- };
- }
-
- [_memoryCache removeAllObjects:memBlock];
- [_diskCache removeAllObjects:diskBlock];
-
- if (group) {
- __weak TMCache *weakSelf = self;
- dispatch_group_notify(group, _queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf);
- });
-
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(group);
- #endif
- }
- }
- - (void)trimToDate:(NSDate *)date block:(TMCacheBlock)block
- {
- if (!date)
- return;
- dispatch_group_t group = nil;
- TMMemoryCacheBlock memBlock = nil;
- TMDiskCacheBlock diskBlock = nil;
-
- if (block) {
- group = dispatch_group_create();
- dispatch_group_enter(group);
- dispatch_group_enter(group);
-
- memBlock = ^(TMMemoryCache *cache) {
- dispatch_group_leave(group);
- };
-
- diskBlock = ^(TMDiskCache *cache) {
- dispatch_group_leave(group);
- };
- }
-
- [_memoryCache trimToDate:date block:memBlock];
- [_diskCache trimToDate:date block:diskBlock];
-
- if (group) {
- __weak TMCache *weakSelf = self;
- dispatch_group_notify(group, _queue, ^{
- TMCache *strongSelf = weakSelf;
- if (strongSelf)
- block(strongSelf);
- });
-
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(group);
- #endif
- }
- }
- #pragma mark - Public Synchronous Accessors -
- - (NSUInteger)diskByteCount
- {
- __block NSUInteger byteCount = 0;
-
- dispatch_sync([TMDiskCache sharedQueue], ^{
- byteCount = self.diskCache.byteCount;
- });
-
- return byteCount;
- }
- #pragma mark - Public Synchronous Methods -
- - (id)objectForKey:(NSString *)key
- {
- if (!key)
- return nil;
-
- __block id objectForKey = nil;
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self objectForKey:key block:^(TMCache *cache, NSString *key, id object) {
- objectForKey = object;
- dispatch_semaphore_signal(semaphore);
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(semaphore);
- #endif
- return objectForKey;
- }
- - (void)setObject:(id <NSCoding>)object forKey:(NSString *)key
- {
- if (!object || !key)
- return;
-
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self setObject:object forKey:key block:^(TMCache *cache, NSString *key, id object) {
- dispatch_semaphore_signal(semaphore);
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(semaphore);
- #endif
- }
- - (void)removeObjectForKey:(NSString *)key
- {
- if (!key)
- return;
-
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self removeObjectForKey:key block:^(TMCache *cache, NSString *key, id object) {
- dispatch_semaphore_signal(semaphore);
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(semaphore);
- #endif
- }
- - (void)trimToDate:(NSDate *)date
- {
- if (!date)
- return;
-
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self trimToDate:date block:^(TMCache *cache) {
- dispatch_semaphore_signal(semaphore);
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(semaphore);
- #endif
- }
- - (void)removeAllObjects
- {
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self removeAllObjects:^(TMCache *cache) {
- dispatch_semaphore_signal(semaphore);
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- #if !OS_OBJECT_USE_OBJC
- dispatch_release(semaphore);
- #endif
- }
- @end
- // HC SVNT DRACONES
|