2012-03-13 6 views
1

Я пытаюсь лучше понять циклы запуска, поскольку они применяются к приложениям Mac (NSRunLoop), но это также может быть более общим вопросом. Документация NSRunLoop говорит:Почему основной цикл запуска и обработка входных данных не требуют процессорного времени?

... ваш код обеспечивает while или for цикл, который приводит в движение цикл выполнения. В вашем цикле используется объект цикла выполнения для «запуска» коды события обработки, который принимает события и вызовов установленных обработчиков

Документов есть пример кода, как это:.

BOOL shouldKeepRunning = YES; 
NSRunLoop *theRL = [NSRunLoop currentRunLoop]; 
while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 

Таким образом, код продолжает вызывать цикл цикла до тех пор, пока не будет принято решение о его прекращении. Метод -runMode:beforeDate: «Запускает цикл один раз, блокируя ввод в указанном режиме до определенной даты». Также существует метод -run, который « приемник в постоянный контур, в течение которого он обрабатывает данные из всех подключенных источников входного сигнала ».

Как можно повторять вызов цикла цикла (или вызов -run, который, по-видимому, делает это сам), не потребляет процессор? Приложение Cocoa может сидеть сложа руки в фоновом режиме, пока выполняется его основной цикл запуска, и он будет потреблять нулевое (или почти нулевое) время CPU.

И в пределах -runMode:beforeDate:, как может быть запущен цикл цикла до тех пор, пока вход не будет принят или таймеры не будут гореть без опроса и потребления процессора?

ответ

1

Это было хорошим предлогом для того, чтобы тыкать в некоторые внутренние элементы Mac OS X! К счастью, соответствующие части Core Foundation являются с открытым исходным кодом.

Обычный ответ на вопрос «Как программа может ждать X, не принимая процессор?» «Ядро это сделал». В этом случае запуск цикла запуска на самом деле просто означает указание ядру, чего вы ожидаете, и затем разрешить переход ядра из ядра. В этом случае цикл запуска тратит большую часть своего времени в mach_msg с флагом MACH_RCV_MSG, который на самом деле является всего лишь системным вызовом в ядре, который заканчивает планирование другого потока для запуска. В конце концов, происходит что-то интересное, что означает, что сообщение Mach отправляется в порт Mach, а ядро ​​пробуждает заблокированный поток и доставляет сообщение. Программы видят это как возвращаемую функцию mach_msg.

Есть все виды способов под капотом, чтобы получить сообщение Маха, отправленное вам. Например, если вы установили NSTimer, это, вероятно, сработает до системного вызова mk_timer_arm, что просто заставляет сообщение Mach отправляться куда-то через определенное время. Таким образом, цикл выполнения не представляет собой бесконечный бесконечный цикл, так как он является диспетчером и отображением между ядром и каркасами Cocoa (или Core Foundation).

Следует сказать, что если ядро ​​приостановило ваш поток, потому что вы ожидаете сообщения, что на самом деле вы не используете какое-либо время процессора, поэтому ваше приложение выглядит неактивным. Зачем беспокоиться о бесконечном цикле, когда у вас есть современное ядро?