Previous section To contents

10.3 Threads example

Let's look at an example of how to work with threads. This program is the same minimal WWW server as in
chapter 9 "File I/O" but it has been re-written to use threads, as you can see it is a lot smaller this way. This is because we can use blocking I/O operations instead of non-blocking and callbacks. This also makes the program much easier to follow:
#!/usr/local/bin/pike

/* A very small threaded httpd capable of fetching files only. * Written by Fredrik Hübinette as a demonstration of Pike */

import Thread;
inherit Stdio.Port;

/* number of bytes to read for each write */
#define BLOCK 16384

/* Where do we have the html files ? */
#define BASE "/home/hubbe/pike/src/"

/* File to return when we can't find the file requested */
#define NOFILE "/home/hubbe/www/html/nofile.html"

/* Port to open */
#define PORT 1905

/* Number of threads to start */
#define THREADS 5

// There will be one of these for each thread
class worker
{
    inherit Stdio.FILE : socket; // For communication with the browser
    inherit Stdio.File : file; // For reading the file from disc

    void create(function accept)
    {
        string cmd, input, tmp;

        while(1)
        {
            socket::close(); // Close previous connection
            file::close();

            object o=accept(); // Accept a connection
            if(!o) continue;
            socket::assign(o);
            destruct(o);

            // Read request
            sscanf(socket::gets(),"%s %s%*[\012\015 \t]",cmd, input);
            if(cmd!="GET")
            {
                werror("Only method GET is supported.\n");
                continue;
            }

            // Open the requested file
            sscanf(input,"%*[/]%s",input);
            input=BASE+combine_path("/",input);
            
            if(!file::open(input,"r"))
            {
                if(!file::open(NOFILE,"r"))
                {
                    werror("Couldn't find default file.\n");
                    continue;
                }
            }

            // Copy data to socket
            while(socket::write(file::read(BLOCK))==BLOCK);
        }
    }
};

int main(int argc, array(string) argv)
{
    werror("Starting minimal threaded httpd\n");

    // Bind the port, don't set it nonblocking
    if(!bind(PORT))
    {
        werror("Failed to open socket (already bound?)\n");
        return 17;
    }

    // Start worker threads
    for(int e=1;e<THREADS;e++) thread_create(worker,accept);
    worker(accept);
}

As stated in the beginning of this chapter; Pike threads are only available on some UNIX systems. The above example does not work if your system does not have threads.


Previous section To contents