Книга: UNIX: разработка сетевых приложений
26.9. Веб-клиент и одновременный доступ
Разделы на этой странице:
26.9. Веб-клиент и одновременный доступ
Изменим код нашего веб-клиента из раздела 26.6: уберем вызов функции Solaris thr_join
и заменим его вызовом функции pthread_join
. Как сказано в разделе 26.6, теперь нам нужно точно указать, завершения какого потока мы ждем. Для этого мы используем условную переменную, описанную в разделе 26.8.
Единственным изменением в отношении глобальных переменных (см. листинг 26.7) является добавление нового флага и условной переменной:
#define F_JOINED 8 /* количество потоков */
int ndone; /* количество завершившихся потоков */
pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ndone_cond = PTHREAD_COND_IINITIALIZER;
Единственным изменением функции do_get_read
(см. листинг 26.9) будет увеличение на единицу значения переменной ndone
и оповещение главного цикла о завершении выполнения потока:
printf("end-of-file on %sn", fptr->f_name);
Close(fd);
Pthread_mutex_lock(&ndone_mutex);
fptr->f_flags = F_DONE; /* сбрасывает флаг F_READING */
ndone++;
Pthread_cond_signal(&ndone_cond);
Pthread_mutex_unlock(&ndone_mutex);
return(fptr); /* завершение выполнения потока */
}
Большинство изменений касается главного цикла, представленного в листинге 26.8. Новая версия показана в листинге 26.13.
Листинг 26.13. Основной рабочий цикл функции main
//threads/web03.c
43 while (nlefttoread > 0) {
44 while (nconn < maxnconn && nlefttoconn > 0) {
45 /* находим файл для считывания */
46 for (i = 0; i < nfiles; i++)
47 if (file[i].f_flags == 0)
48 break;
49 if (i == nfiles)
50 err_quit("nlefttoconn = %d but nothing found", nlefttoconn);
51 file[i].f_flags = F_CONNECTING;
52 Pthread_create(&tid, NULL, &do_get_read, &file[i]);
53 file[i].f_tid = tid;
54 nconn++;
55 nlefttoconn--;
56 }
57 /* Ждем завершения выполнения одного из потоков */
58 Pthread_mutex_lock(&ndone_mutex);
59 while (ndone == 0)
60 Pthread_cond_wait(&ndone_cond, &ndone_mutex);
61 for (i = 0; i < nfiles; i++) {
62 if (file[i].f_flags & F_DONE) {
63 Pthread_join(file[i].f_tid, (void**)&fptr);
64 if (&file[i] != fptr)
65 err_quit("file[i] != fptr");
66 fptr->f_flags = F_JOINED; /* clears F_DONE */
67 ndone--;
68 nconn--;
69 nlefttoread--;
70 printf("thread %d for %s donen", fptr->f_tid, fptr->f_name);
71 }
72 }
73 Pthread_mutex_unlock(&ndone_mutex);
74 }
75 exit(0);
76 }
По возможности создаем новый поток
44-56
Эта часть кода не изменилась.
Ждем завершения выполнения потока
57-60
Мы ждем завершения выполнения потоков, отслеживая, когда значение ndone
станет равно нулю. Как сказано в разделе 26.8, эта проверка должна быть проведена перед тем, как взаимное исключение будет блокировано, а переход потока в состояние ожидания осуществляется функцией pthread_cond_wait
.
Обработка завершенного потока
61-73
Когда выполнение потока завершилось, мы перебираем все структуры file
, отыскивая соответствующий поток, вызываем pthread_join
, а затем устанавливаем новый флаг F_JOINED
.
В табл. 16.1 показано, сколько времени требует выполнение этой версии веб-клиента, а также версии, использующей неблокируемую функцию connect
.
- 26.1. Введение
- 26.2. Основные функции для работы с потоками: создание и завершение потоков
- 26.3. Использование потоков в функции str_cli
- 26.4. Использование потоков в эхо-сервере TCP
- 26.5. Собственные данные потоков
- 26.6. Веб-клиент и одновременное соединение (продолжение)
- 26.7. Взаимные исключения
- 26.8. Условные переменные
- 26.9. Веб-клиент и одновременный доступ
- 26.10. Резюме
- Упражнения
- Как получить снимок с веб-камеры?
- Совместимость клиентов и серверов различных версий
- Клиенты 3-го диалекта
- Аватар идеального клиента
- Что делать, если при установке принтера появляется сообщение Невозможно завершение операции. Подсистема печати недоступн...
- Одновременный запуск нескольких копий сервера (multi-instancing)
- Определение версии клиента
- 9.4. Права доступа к squid
- Снятие ответственности с клиента
- Приложение 21 Образец должностной инструкции начальника отдела по работе с сетевыми клиентами
- 4. Стадии бизнес-процесса взаимодействия с клиентами
- Глава 29 Доступ к канальному уровню