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 Socket) server.accept();
// Update numAlive based on any outstanding messages
bool received = true;
while (received) {
received = false;
receiveTimeout(dur!"msec"(0),
(int completed) { --numAlive; received = true; }
);
}
if (numAlive < 10) {
spawn(&respond, thisTid, cacheTid);
numAlive++;
} else {
spawn(&sendServerBusy, thisTid);
}
// 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(tid, count); }, // 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 Socket) server.accept();
send(countTid, thisTid);
if (receiveOnly!int() < 10) {
spawn(&respond, thisTid, cacheTid, countTid);
send(countTid, 1); // increment client count
} else {
spawn(&sendServerBusy, thisTid);
}
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();”.

