Luke
Luke

Reputation: 1377

Handling threads in server application after clients disconnect

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

Answers (1)

ratchet freak
ratchet freak

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

Related Questions