Комментатор AnotherMatt интересуется, почему консольные программы Win32 получают уведомления в фоновом потоке. Почему бы не отправлять их в главный поток?
Вообще-то, позвольте мне задать обратный вопрос: почему Unix отправляет уведомления в главный поток? Ведь это делает почти невозможным сделать в обработчике хоть что-то полезное. Код главного потока в момент вызова уведомления может находится внутри вызова функций менеджера памяти (удерживая блокировку критической секции). И если обработчик попытается выполнить любую операцию, требующую выделения памяти, то он просто заблокирует сам себя (если вам повезло) или испортит данные в куче (если вам не повезло).
К примеру, посмотрите на такой обработчик:
procedure catch_int(sig_num: Integer); cdecl; begin // Переустанавливаем обработчик для следующего уведомления signal(SIGINT, catch_int); // и выводим сообщение WriteLn('Don''t do that'); Flush(Output); end;Что произойдёт, если обработчик будет вызван как раз в тот момент, когда основная программа выполняла вызов
Flush
, скажем, когда она сбросила половину буфера? Если бы второй вызов был сделан из второго потока, то второй вызов ожидал бы завершения первого (многопоточная синхронизация), но в данном случае оба вызова делает один и тот же поток. Второй вызов не может ожидать завершения работы первого, потому что первый вызов не может завершиться, пока не отработал второй!(Заметьте, что такой обработчик также может потенциально менять
errno
(аналог GetLastError
), что приведёт к "невозможным" ошибкам в главном коде).Win32 не использует модель асинхронного прерывания пользовательского кода другим пользовательским кодом, потому что при этом невозможно достоверно судить о состоянии процесса. Доставка консольных уведомлений в фоновый поток означает, что если второй поток попытается получить доступ к куче или иному ресурсу, занятому главным потоком, то он просто будет покорно ожидать, когда главный поток завершит работу с ресурсом, прежде чем изменять его.
Прим.пер.: см. также.
Спасибо, это то что я искал.
ОтветитьУдалить