0

ディスクに保存されている同じリソースに対して複数の読み取り操作を実行しています。

場合によっては、読み取り操作自体が、同じリソースに対する要求間の時間よりも長くかかることがあります。そのような場合、読み取り操作をディスクからの 1 つの読み取り要求にまとめてから、同じ結果をさまざまな要求元に返すことが理にかなっています。

最初に、最初のフェッチ リソース リクエストの結果をキャッシュしようとしましたが、リソースの読み取りに時間がかかりすぎて、新しいリクエストが入ってきたため、これは機能しませんでした。つまり、リソースもフェッチしようとすることになります。

すでに進行中のリクエストに追加のリクエストを「追加」することはできますか?

私が今持っているコードは、この基本構造に従っています (これでは十分ではありません)。

-(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 に答える