Хотя мой опыт работы с Windows NT, «имена» функций - это имена, которые присваивают имена общим функциям потоков или процессам, которые должны быть доступны в любой многопоточной среде.
Если основной поток может определить, когда дочерний поток должен быть прерван, он может сделать это, установив цикл дочернего потока в логическое значение, например "terminate_conditon", или завершив поток через дескриптор.
// child thread
terminate_condition=FALSE;
while (!terminate_condition)
{
// accept connections
}
child_thread_done=TRUE;
// output results
exit_thread ();
// main thread
child_thread_done=FALSE;
child_thread=create_thread (...);
// monitor connections to determine when done
terminate_condition=TRUE;
while (!child_thread_done)
{
sleep (1);
}
// or maybe output results here?
exit_process ();
Это решение с контролируемым завершением требует, чтобы только один поток записывал в логическое значение child_thread_done, а любой другой поток только читал.
Или
// child thread
while (1)
{
// accept connections
}
// main thread
child_thread=create_thread (...);
// monitor connections to determine when done
kill_thread (child_thread);
// output results
exit_process ();
Вторая форма сложнее, так как она просто убивает дочерний поток. В целом, лучше, чтобы дочерний поток выполнял контролируемое завершение, особенно если он выделил ресурсы (которые становятся обязанностью процесса в целом, а не только выделяющего потока).
Если есть много дочерних потоков, работающих с соединениями, необходим механизм синхронизированного завершения: либо структура с таким количеством членов, сколько имеется дочерних потоков (завершающий поток устанавливает свой «завершенный» логический значение равным true, завершается, и основной поток отслеживает структура, гарантирующая, что все дочерние «завершенные» логические значения являются истинными перед продолжением) или счетчик, содержащий число работающих дочерних потоков (когда дочерний процесс собирается завершиться, он получает исключительный контроль над счетчиком с помощью спин-блокировки, уменьшает его и освобождает блокировка перед завершением: основной поток ничего не делает, пока счетчик не содержит ноль).