Задача-c, как пакетировать несколько операций чтения

Я выполняю несколько операций чтения на одном и том же ресурсе, хранящемся на диске.

Иногда сама операция чтения занимает больше времени, чем время между запросами к тому же ресурсу. В этих случаях имеет смысл объединить операции чтения в один запрос на чтение с диска и затем вернуть один и тот же результат различным запросчикам.

Первоначально я пытался кэшировать результат из исходного запроса на выборку ресурса - но это не сработало, потому что время, затрачиваемое на чтение ресурса, было слишком длинным, и приходили новые запросы - это означало, что они также будут пытаться получить ресурс.

Можно ли "добавить" дополнительные запросы к тем, которые уже выполняются?

Код, который у меня есть, теперь следует этой базовой структуре (которая недостаточно хороша):

-(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;
        });
    });
}

1 ответ

Я думаю, что вы хотите ввести вспомогательный объект

@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)

Это не скомпилированный код, поэтому, пожалуйста, проверьте орфографию и логику, но я надеюсь, что это объясняет идею. Мне нравится этот пост, если вы хотите познакомиться с семафорами.

Другие вопросы по тегам