QNX/UNIX: Анатомия параллелизма
QNX/UNIX: Анатомия параллелизма читать книгу онлайн
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.
В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Обе рассмотренные функции установок [23]параметров отмены при успешном выполнении возвращают значение EOK.
Итак, действия потока на запрос его завершения будут определяться текущей комбинацией двух установленных для него параметров: состоянием и типом отмены.
Теперь о том, чем же отличается отмена асинхронно и синхронно завершаемых потоков. Поток с асинхронным типом отмены (установленный с
PTHREAD_CANCEL_ASYNCHRONOUS
PTHREAD_CANCEL_DEFERRED
pthread_cancel()
void pthread_testcancel(void);
Каждый вызов
pthread_testcancel()
pthread_testcancel()
PTHREAD_CANCEL_DISABLE
pthread_testcancel()
( Очень важно!) Достаточно много библиотечных функций могут сами устанавливать точки отмены. Более того, такие функции могут косвенно вызываться из других функций в программе и тем самым неявно устанавливать точки отмены. Информацию о таких функциях следует искать в справочной man-странице по функции
pthread_testcancel()
pthread_testcancel()
Если состояние отмены потока, как это описывалось ранее, установлено в
PTHREAD_CANCEL_DISABLE
Покажем, как могут быть использованы все эти предосторожности в коде функции потока, чтобы сделать код безопасным с позиции возможной асинхронной отмены потока извне:
void* function(void* data) {
int state;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
// ... здесь выполняется инициализация ...
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_setcancelstate(&state, NULL);
while (true) {
struct blockdata *blk = new blockdata;
// ... обработка блока данных blk ...
delete blk;
pthread_testcancel();
}
}
...
pthread_t tid;
...
pthread_create(&tid, NULL, function, NULL);
...
pthread_cancel(tid); // отмена потока
void* res;
pthread_join(tid, &res); // ожидание отмены
if (res != PTHREAD_CANCELED)
cout << "Что-то не так!" << endl;
Наконец, в QNX (но не в POSIX) существует вызов, подобный
pthread_cancel()
int pthread_abort(pthread_t thread);
В отличие от
pthread_cancel()
pthread_join()
void*
PTHREAD_ABORTED
PTHREAD_CANCELED
pthread_cancel()
Но и этих мер безопасности недостаточно на все случаи жизни, поэтому механизм потоков предусматривает еще один уровень (механизм) страховки.
Стек процедур завершения
Для поддержания корректности состояния объектов процесса каждый поток может помещать (добавлять) в стек процедур завершения (thread's cancellation-cleanup stack) функции, которые при завершении (
pthread_exit()
return
pthread_cancel()
void pthread_cleanup_push(void (routine)(void*), void* arg);
где
routine
arg
Функции завершения (начиная с вершины стека) вызываются со своими блоками данных в случаях, когда:
• поток завершается, выполняя
pthread_exit()
• активизируется действие отмены потока, ранее запрошенное по вызову
pthread_cancel()
• выполняется второй (комплементарный к
pthread_cleanup_push()
void pthread_cleanup_pop(int execute);
Этот вызов выталкивает из стека последнюю помещенную туда
pthread_cleanup_push()
execute