У меня есть объект NSRunLoop, к которому я привязываю таймеры и потоки. Он отлично работает. Остановка - это еще одна история.
Я запускаю цикл, используя [runLoop run]
.
Если я попытаюсь остановить цикл, используя CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])
, цикл не остановится. Если я запустил цикл, используя CRunLoopRun()
, он будет работать. Я также удостоверился, что вызов выполняется в правильном потоке (тот, который запускает мой собственный цикл выполнения). Я отлаживал это с помощью pthread_self()
.
Я нашел архив списка рассылки, в котором разработчик сказал: "Не беспокойтесь, используя CRunLoopStop()
, если вы запустили цикл, используя метод run NSRunLoop
". Я могу понять, почему так оно и есть - вы обычно соединяете инициализаторы и финализаторы из одного и того же набора функций.
Как вы останавливаете NSRunLoop
без "обращения к CF"? Я не вижу метод stop
на NSRunLoop
. В документах указано, что вы можете остановить цикл запуска тремя способами:
- Настройте цикл выполнения для запуска со значением таймаута
- Сообщите, чтобы цикл выполнения прекратил использование
CFRunLoopStop()
- Удалите все исходные источники, но это ненадежный способ остановить цикл цикла, потому что вы никогда не сможете узнать, что застряло в цикле выполнения за спиной.
Ну, я уже пробовал 2. и там "уродливое" чувство, потому что вам нужно копать в CF. 3. Не может быть и речи - я не представляю себе не детерминированный код.
Это оставляет нам 1. Если я правильно понимаю документы, вы не можете "добавить" тайм-аут к уже существующему циклу запуска. Вы можете запускать только новые циклы запуска с таймаутом. Если я запустил новый цикл выполнения, он не решит мою проблему, так как он создаст только замкнутый цикл цикла. Я все равно вернусь обратно в старый, так же, как я хотел остановиться... верно? Возможно, я неправильно понял это. Кроме того, я не хочу запускать цикл со значением тайм-аута. Если я это сделаю, мне придется сделать компромисс между сжиганием циклов процессора (значение низкого тайм-аута) и отзывчивостью (с высоким значением таймаута).
Это настройка, которую я имею прямо сейчас (псевдокод-ish):
Communicator.h
@interface Communicator : NSObject {
NSThread* commThread;
}
-(void) start;
-(void) stop;
@end
Communicator.m
@interface Communicator (private)
-(void) threadLoop:(id) argument;
-(void) stopThread;
@end
@implementation Communicator
-(void) start {
thread = [[NSThread alloc] initWithTarget:self
selector:@selector(threadLoop:)
object:nil];
[thread start];
}
-(void) stop {
[self performSelector:@selector(stopThread)
onThread:thread
withObject:self
waitUntilDone:NO];
// Code ommitted for waiting for the thread to exit...
[thread release];
thread = nil;
}
@end
@implementation Communicator (private)
-(void) stopThread {
CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
}
-(void) threadLoop:(id) argument {
// Code ommitted for setting up auto release pool
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
// Code omitted for adding input sources to the run loop
CFRunLoopRun();
// [runLoop run]; <- not stoppable with
// Code omitted for draining auto release pools
// Code omitted for signalling that the thread has exited
}
@endif
Что мне делать? Является ли это распространенным/хорошим шаблоном, чтобы возиться с CF? Я недостаточно хорошо знаю Фонд. Является ли вмешательство в уровень CF опасным (в отношении повреждения памяти, несоответствий, утечек памяти)? Есть ли лучший образец для достижения того, чего я пытаюсь достичь?