Reputation: 1377
I'm currently working on simple HTTP server. I use Winsock and standard threads from C++11. For each connected (accepted) client there is new thread created.
std::map<SOCKET, std::thread> threads;
bool server_running = true;
while(server_running) {
SOCKET client_socket;
client_socket = accept(listen_socket, NULL, NULL);
if(client_socket == INVALID_SOCKET) {
// some error handling
}
threads[client_socket] = std::thread(clientHandler, client_socket);
}
clientHandler
function looks generally like this:
while(1) {
while(!all_data_received) {
bytes_received = recv(client_socket, recvbuf, recvbuflen, 0);
if(bytes_received > 0) {
// do something
} else {
goto client_cleanup;
}
}
// do something
}
client_cleanup: // we also get here when Connection: close was received
closesocket(client_socket);
And here we come to my problem - how to handle all the threads which ended but haven't been joined with main thread and references to them still exist in threads
map?
The simplest solution would be probably to iterate over threads
frequently (e.q. from another thread?) and join and delete those which returned.
Please share your expertise. :)
PS. Yes, I know about thread pool pattern. I'm not using it in my app (for better or worse). I'm looking for answer concerning my current architecture.
Upvotes: 0
Views: 406
Reputation: 48196
Simple solution? Just detach()
after you start the thread. This will mean that once the thread terminates the resources will be cleaned up and you don't need to keep the std::map<SOCKET, std::thread> threads
.
std::thread(clientHandler, client_socket).detach();
Otherwise create a thread-safe LIFO queue where during cleanup you push the socket to it.
Then in the main loop you alternately check accept
and that queue and when the queue has sockets in them you do threads.erase(socket);
for each socket in the queue.
However if you do that then you may as well putt he LIFO in the other direction and use a thread pool.
Upvotes: 2