Свойства потоков
Для досрочного завершения потока можно воспользоваться функцией pthread_cancel. Единственным аргументом этой функции является идентификатор потока. Функция pthread_cancel() возвращает 0 в случае успеха и ненулевое значение в случае ошибки. Несмотря на то, что pthread_cancel() может завершить поток досрочно, ее нельзя назвать средством принудительного завершения потоков. Дело в том, что поток может не только самостоятельно выбрать порядок завершения в ответ на вызов pthread_cancel(), но и вовсе игнорировать этот вызов. Вызов функции pthread_cancel() есть запрос на выполнение досрочного завершения потока.
Свойства потоков Функция pthread_setcancelstate определяет, будет ли поток реагировать на обращение к нему с помощью pthread_cancel(), или не будет. У функции pthread_setcancelstate() два параметра, параметр state типа int и параметр oldstate типа «указатель на int». В первом параметре передается новое значение, указывающее, как поток должен реагировать на запрос pthread_cancel(), а в переменную, чей адрес был передан во втором параметре, функция записывает прежнее значение. Если прежнее значение вас не интересует, во втором параметре можно передать NULL.
Свойства потоков Чаще всего функция pthread_setcancel- state() используется для временного запрета завершения потока. Допустим, при определенных условиях программа может потребовать его досрочного завершения. Но в нашем потоке есть участок кода, во время выполнения которого завершать поток крайне нежелательно. Можно оградить этот участок кода от досрочного завершения с помощью пары вызовов: pthread_setcancelstate(PTHREAD_CANCEL_ DISABLE, NULL);... //Здесь поток завершать нельзя pthread_setcancelstate(PTHREAD_CANCEL_ ENABLE, NULL);
Свойства потоков Первый вызов pthread_setcancelstate() запрещает досрочное завершение потока, второй – разрешает. Если запрос на досрочное завершение потока поступит в тот момент, когда поток игнорирует эти запросы, выполнение запроса будет отложено до тех пор, пока функция pthread_setcancelstate() не будет вызвана с аргументом PTHREAD_CANCEL_ENABLE. Рассмотрим пример программы. Первый вызов pthread_setcancelstate() запрещает досрочное завершение потока, второй – разрешает. Если запрос на досрочное завершение потока поступит в тот момент, когда поток игнорирует эти запросы, выполнение запроса будет отложено до тех пор, пока функция pthread_setcancelstate() не будет вызвана с аргументом PTHREAD_CANCEL_ENABLE. Рассмотрим пример программы. пример
Свойства потоков В самом начале функции потока thread_func() мы запрещаем досрочное завершение потока, затем выводим четыре тестовых сообщения с интервалом в одну секунду, после чего разрешаем досрочное завершение. Далее, с помощью функции pthread_testcancel(), мы создаем точку отмены (cancellation point) потока. Если досрочное завершение потока было затребовано, в этот момент поток должен завершиться. Затем мы выводим еще одно диагностическое сообщение, которое пользователь не должен видеть, если программа сработает правильно. В самом начале функции потока thread_func() мы запрещаем досрочное завершение потока, затем выводим четыре тестовых сообщения с интервалом в одну секунду, после чего разрешаем досрочное завершение. Далее, с помощью функции pthread_testcancel(), мы создаем точку отмены (cancellation point) потока. Если досрочное завершение потока было затребовано, в этот момент поток должен завершиться. Затем мы выводим еще одно диагностическое сообщение, которое пользователь не должен видеть, если программа сработает правильно.
Свойства потоков В главной функции программы мы создаем поток, затем дожидаемся, пока значение глобальной переменной i станет больше нуля (это гарантирует нам, что поток уже запретил досрочное завершение) и вызываем функцию pthread_cancel(). После этого мы переходим к ожиданию завершения потока с помощью pthread_join(). Если вы скомпилируете и запустите программу, то увидите, что поток распечатает четыре тестовых сообщения Im still running! (после первого сообщения главная функция программы выдаст запрос на завершение потока). В главной функции программы мы создаем поток, затем дожидаемся, пока значение глобальной переменной i станет больше нуля (это гарантирует нам, что поток уже запретил досрочное завершение) и вызываем функцию pthread_cancel(). После этого мы переходим к ожиданию завершения потока с помощью pthread_join(). Если вы скомпилируете и запустите программу, то увидите, что поток распечатает четыре тестовых сообщения Im still running! (после первого сообщения главная функция программы выдаст запрос на завершение потока). Поскольку поток завершится досрочно, последнего тестового сообщения вы не увидите. Поскольку поток завершится досрочно, последнего тестового сообщения вы не увидите.
Свойства потоков Интересна роль функции pthread_testcancel(). Как уже отмечалось, эта функция создает точку отмены потока. Зачем нужны особые точки отмены? Дело в том, что даже если досрочное завершение разрешено, поток, получивший запрос на досрочное завершение, может завершить работу не сразу. Если поток находится в режиме отложенного досрочного завершения (именно этот режим установлен по умолчанию), он выполнит запрос на досрочное завершение, только достигнув одной из точек отмены. В соответствии со стандартом POSIX, точками отмены являются вызовы многих «обычных» функций, например open(), pause() и write(). Интересна роль функции pthread_testcancel(). Как уже отмечалось, эта функция создает точку отмены потока. Зачем нужны особые точки отмены? Дело в том, что даже если досрочное завершение разрешено, поток, получивший запрос на досрочное завершение, может завершить работу не сразу. Если поток находится в режиме отложенного досрочного завершения (именно этот режим установлен по умолчанию), он выполнит запрос на досрочное завершение, только достигнув одной из точек отмены. В соответствии со стандартом POSIX, точками отмены являются вызовы многих «обычных» функций, например open(), pause() и write().
Свойства потоков Про функцию printf() в документации сказано, что она может быть точкой отмены, но в Linux при попытке остановиться на printf() происходит нечто странное – поток завершается, но pthread_join() не возвращает управления. Поэтому мы создаем явную точку отмены с помощью вызова pthread_testcancel(). Про функцию printf() в документации сказано, что она может быть точкой отмены, но в Linux при попытке остановиться на printf() происходит нечто странное – поток завершается, но pthread_join() не возвращает управления. Поэтому мы создаем явную точку отмены с помощью вызова pthread_testcancel(). Закомментировав строку Закомментировав строку pthread_testcancel(); pthread_testcancel(); и перекомпилировав программу, увидим этот эффект. и перекомпилировав программу, увидим этот эффект.
Свойства потоков Впрочем, мы можем выполнить досрочное завершение потока, не дожидаясь точек останова. Для этого необходимо перевести поток в режим немедленного завершения, что делается с помощью вызова pthread_setcanceltype(PTHREAD_CANCEL_ ASYNCHRONOUS, NULL); Впрочем, мы можем выполнить досрочное завершение потока, не дожидаясь точек останова. Для этого необходимо перевести поток в режим немедленного завершения, что делается с помощью вызова pthread_setcanceltype(PTHREAD_CANCEL_ ASYNCHRONOUS, NULL); Раскомментировав эту строку и перекомпилировав программу, увидим, что беспокоиться о точках останова уже не нужно. Раскомментировав эту строку и перекомпилировав программу, увидим, что беспокоиться о точках останова уже не нужно. Вызов pthread_setcanceltype(PTHREAD_CANCEL_ DEFERRED, NULL); снова переводит поток в режим отложенного досрочного завершения. Вызов pthread_setcanceltype(PTHREAD_CANCEL_ DEFERRED, NULL); снова переводит поток в режим отложенного досрочного завершения.