30 Sep — D Web server, cont'd

We previously saw a Web server built in D. It creates a new thread for every client, but real Web servers will have a threshold of how many clients they'll deal with simultaneously, since more clients will just bog down server performance without actually improving the server success.

So now we ask: How can we modify this Web server to include such a threshold, say at most 10 clients at any time?

Approach A — counter in main

So that main knows when a client is done, we modify the respond function to include a line saying “send(callerTid-1)” just before “socket.close();”. Then we modify main to maintain a counter.

void main() {
    Tid cacheTid = spawn(&cacheServer);

    Socket server = new TcpSocket;
    server.bind(new InternetAddress(httpPort));
    server.listen(10);

    int numAlive = 0;
    while (true) {
        clientSocket = cast(shared Socketserver.accept();

        // Update numAlive based on any outstanding messages
        bool received = true;
        while (received) {
            received = false;
            receiveTimeout(dur!"msec"(0),
                (int completed) { --numAlivereceived = true; }
            );
        }

        if (numAlive < 10) {
            spawn(&respondthisTidcacheTid);
            numAlive++;
        } else {
            spawn(&sendServerBusythisTid);
        }

        // Wait until client is done with "clientSocket." But we
        // some threads may complete their work first.
        bool clientStarted = false;
        while (!clientStarted) {
            receive(
                (bool started) { clientStarted = true; },
                (int completed) { numAlive--; }
            );
        }
    }
}

Approach B — counter in separate thread

Alternatively, we could have a separate thread that maintains the counter, akin to the cacheServer function. This would be a “purer” message-passing technique.

void countServer() {
    int count = 0;

    while (true) {
        receive(
            (Tid tid) { send(tidcount); }, // request current count
            (int delta) { count += delta; }  // update current count
        );
    }
}

We would have to modify main as follows.

void main() {
    Tid cacheTid = spawn(&cacheServer);
    Tid countTid = spawn(&countServer);

    Socket server = new TcpSocket;
    server.bind(new InternetAddress(httpPort));
    server.listen(10);

    while (true) {
        clientSocket = cast(shared Socketserver.accept();

        send(countTidthisTid);
        if (receiveOnly!int() < 10) {
            spawn(&respondthisTidcacheTidcountTid);
            send(countTid1); // increment client count
        } else {
            spawn(&sendServerBusythisTid);
        }

        receiveOnly!bool(); // don't continue until thread got clientSocket
    }
}

Finally, we'd need to modify respond to decrement the count once it is complete. We'd add a new parameter to respond named countTid, so that respond knows who to notify once it is done. (Note that we modified main to pass this parameter into respond.) Then we modify respond function to include the line “send(countTid-1)” just before “socket.close();”.