0

我正在对存储在磁盘上的同一资源执行多个读取操作。

有时,读取操作本身比对同一资源的请求之间的时间要长。在这些情况下,将读取操作批量处理为来自磁盘的一个读取请求,然后将相同的结果返回给各个请求者是有意义的。

最初我尝试缓存来自初始获取资源请求的结果 - 但这不起作用,因为读取资源所花费的时间太长,并且新请求进来 - 这意味着他们也会尝试获取资源。

是否可以将附加请求“附加”到已经在进行中的请求?

我现在拥有的代码遵循这个基本结构(这还不够好):

-(void)fileForKey:(NSString *)key completion:(void(^)(NSData *data) {
    NSData *data = [self.cache threadSafeObjectForKey:key];
    if (data) {
        // resource is cached - so return it - no need to read from the disk
        completion(data);
        return;
    }
    // need to read the resource from disk
    dispatch_async(self.resourceFetchQueue, ^{
        // this could happen multiple times for the same key - because it could take a long time to fetch the resource - all the completion handlers should wait for the resource that is fetched the first time
        NSData *fetchedData = [self fetchResourceForKey:key];
        [self.cache threadSafeSetObject:fetchedData forKey:key];
        dispatch_async(self.completionQueue, ^{
            completion(fetchedData);
            return;
        });
    });
}
4

1 回答 1

0

我想你想引入一个辅助对象

@interface CacheHelper{
  @property (nonatomic, copy) NSData *data;
  @property (nonatomic, assign) dispatch_semaphore_t dataReadSemaphore;
}

您的阅读器方法现在变成了类似

CacheHelper *cacheHelper = [self.cache threadSafeObjectForKey:key]
if (cacheHelper && cacheHelper.data) 
{
   completion(cacheHelper.data);
   return;
}
if (cacheHelper)
{
   dispatch_semaphore_wait(cacheHelper.dataReadSemaphore, DISPATCH_TIME_FOREVER);
   dispatch_semaphore_signal(cacheHelper.dataReadSemaphore);
   completion(cacheHelper.data)
   return;
}
cacheHelper = [[CacheHelper alloc] init]
cacheHelper.dataReadSemaphore = dispatch_semaphore_create(0);
cacheHelper.data = [self fetchResourceForKey:key];
[self.cache threadSafeSetObject:cacheHelper forKey:key];
dispatch_semaphore_signal(cacheHelper.dataReadSemaphore);
completion(cacheHelper.data)

这是未编译的代码,所以请检查拼写和逻辑,但我希望它能解释这个想法。如果您想了解信号量,我喜欢这篇文章。

于 2014-08-17T16:33:11.643 回答