Эта функция обычно вызывается потоком при необходимости изменить собственный статус в следующем формате:
pthread_detach(pthread_self);
Функция pthread_exit
Одним из способов завершения потока является вызов функции
pthread_exit
.#include pthread.h
void pthread_exit(void *
Если поток не является отсоединенным, идентификатор потока и статус завершения сохраняются до того момента, пока какой-либо другой поток данного процесса не вызовет функцию
pthread_join
.Указатель
status
не должен указывать на объект, локальный по отношению к вызывающему потоку, так как этот объект будет уничтожен при завершении потока.Существуют и другие способы завершения потока.
Функция, которая была вызвана потоком (третий аргумент функции
pthread_create
), может возвратить управление в вызывающий процесс. Поскольку, согласно своему объявлению, эта функция возвращает указатель
void
, возвращаемое ею значение играет роль статуса завершения данного потока.Если функция
main
данного процесса возвращает управление или любой поток вызывает функцию
exit
, процесс завершается вместе со всеми своими потоками.26.3. Использование потоков в функции str_cli
В качестве первого примера использования потоков мы перепишем нашу функцию
str_cli
. В листинге 16.6 была представлена версия этой функции, в которой использовалась функция
fork
. Напомним, что были также представлены и некоторые другие версии этой функции: изначально в листинге 5.4 функция блокировалась в ожидании ответа и была, как мы показали, далека от оптимальной в случае пакетного ввода; в листинге 6.2 применяется блокируемый ввод-вывод и функция
select
; версии, показанные в листинге 16.1 и далее, используют неблокируемый ввод-вывод.На рис. 26.1 показана структура очередной версии функции str_cli, на этот раз использующей потоки, а в листинге 26.1
[1]представлен код этой функции.Рис. 26.1
. Измененная функция str_cli, использующая потокиЛистинг 26.1
. Функция str_cli, использующая потоки//threads/strclithread.c
1 #include "unpthread.h"
2 void *copyto(void*);
3 static int sockfd; /* глобальная переменная, доступная обоим потокам */
4 static FILE *fp;
5 void
6 str_cli(FILE *fp_arg, int sockfd_arg)
7 {
8 char recvline[MAXLINE];
9 pthread_t tid;
10 sockfd = sockfd_arg; /* копирование аргументов во внешние переменные */
11 fp = fp_arg;
12 Pthread_create(tid, NULL, copyto, NULL);
13 while (Readline(sockfd, recvline. MAXLINE) 0)
14 Fputs(recvline, stdout);
15 }
16 void*
17 copyto(void *arg)
18 {
19 char sendline[MAXLINE];
20 while (Fgets(sendline, MAXLINE, fp) != NULL)
21 Writen(sockfd, sendline, strlen(sendline));
22 Shutdown(sockfd, SHUT_WR); /* признак конца файла в стандартном
потоке ввода, отправка сегмента FIN */
23 return (NULL);
24 /* завершение потока происходит, когда в стандартном потоке ввода
встречается признак конца файла */
25 }
1
unpthread.h
. Он включает наш обычный заголовочный файл
unp.h
, затем — заголовочный файл POSIX
pthread.h
, и далее определяет прототипы наших потоковых функций-оберток для
pthread_XXX
(см. раздел 1.4), название каждой из которых начинается с
Pthread_
.10-11
str_cli
:
fp
— указатель на структуру
FILE
для входного файла, и
sockfd
— сокет TCP, связанный с сервером. Для простоты мы храним эти два значения во внешних переменных. Альтернативой является запись этих двух значений в структуру, указатель на которую затем передается в качестве аргумента создаваемому потоку.