Поэтому в свободное время я работаю над «движком» HTTP-запросов. То, что я пытаюсь создать, - это «движок», который генерирует ответ на запрос/анализ общего объекта для приложения iphone.
И самое главное, он должен _всегда_ вызывать пользовательский интерфейс.
Что бы ни случилось (тайм-аут NSURLRequest/ошибка синтаксического анализа/возбуждение NSExcept) (может быть, когда-нибудь и SIG?)
Поэтому я создал что-то кровавое, используя блоки и dispatch_once. Это работает, но у меня есть это предупреждение Clang. Я имею в виду, что мои запросы работают, и в случае исключения пользовательский интерфейс вызывается один раз, по-видимому.
Вызов «dispatch_once» использует локальную переменную «once» для значения предиката. Использование такой временной памяти для предиката потенциально опасно.
В этом суть проблемы
// invoke a bloc in a proper thread with a proper autorelease / trycatch / logs
static inline void api_dispatch_concurrent(EngineOnceCallback block, SEL caller, EngineCallback callback) {
dispatch_async(APIengineQueue(), ^{ // serial dispatch_queue
@autoreleasepool {
dispatch_once_t once = 0;
@try {
// block may callback using 'once'
(block) ? block(once) : NULL;
}
@catch (NSException *exception) {
[[ACLogs sharedLogs] logException:exception caller:caller
class:[ACRetroscopeEngine class]];
APILog(@"NSException invoking API block:%@", exception);
dispatch_once(&once, ^{
APILog(@"Perform callback as recover from exception");
ACResponse *defaultResponse = [ACResponse responseWithException:exception];
try_catch(block_safe_invoke_main_thread(callback, defaultResponse));
});
}
@finally {
}
}
});
}
Некоторые макросы, используемые там:
#define block_safe_invoke(block, ...) (block != NULL) ? block(__VA_ARGS__) : NULL;
#define block_safe_invoke_main_thread(block, ...) \
if ([NSThread isMainThread]) { \
block_safe_invoke(block, __VA_ARGS__) \
} else { \
dispatch_sync(dispatch_get_main_queue(), ^{ \
block_safe_invoke(block, __VA_ARGS__) \
}); \
} \
Заранее спасибо :р