Dit is een archief-pagina

Dit is een archief-pagina. Ik werk deze pagina niet meer actief bij.
Informatie kan verouderd zijn, en links lopen mogelijk dood.
Maar, misschien heeft iemand er nog wat aan.


CLWP Thread Library

This page is also available in Dutch

I wanted to play with multi-threading (a kind of multi-tasking, but within the same program running multiple 'threads' in the same memory space, so sharing e.g. globaldata structures and variables). I first looked at existing solutions like pthreads and the GNU pth library (look at the bottom of this page for comments), but these did not suite my needs.

I needed such a package to be used together with the Allegro game library (but it is in no way dependent on it), to animate multiple independent objects (players, computer-controlled figures) in an easy programming model. For example, in my Pinpin game (written in Allegro), this is great to handle the baby pinguins, which can act independently from the parent, e.g. to swim back to their starting locations. Actually, I would appriciate this kind of functionality in Allegro itself.

Especially pthreads did compile perfectly, but was too heavy-weight for my purpose. I wanted to use this in my games (see my games page) to animate independent figures without having to do all kind of programming tricks, by giving each of them their own thread of control. However, pthreads is a full-blown pre-emptive multi-threading package (great!), meaning that e.g. driven by a timer the current thread can be interrupted at any moment, and a switch to the next thread will take place (e.g. every 20 millisecond). Disadvantage of this is that each thread must be always able to give up control, and especially the C standard libraries are not re-entrant (can not run multiple instances at the same time). I was more looking for a co-operative multi-threading approach, where threads explicitely give up control to run a next thread (also a bit comparable to co-routines).

So I started my own implementation named CLWP (Co-operative Ligth-Weight Processes), based on LWP, a light-weight threading package of Josh Turpen intended for the DJGPP compiler (GNU under DOS). Was also pre-emptive, but I stripped this. As LWP was only a very small package (two small source files, one C, one assembly) this was fairly streigthforward, just a couple of hours work (after reading the documentation). Thanks, Josh! Making and running the documentation and test code was more of an effort, especially the performance timing was completely wrong (example 4) in release 1.1. But: I now have timed the task switch at less than 0.25 microsecond per switch! (1GHz Pentium-III, runtime measurement in Windows-ME environment).

You can download my first 'final release': clwp13.zip file versie 1.3 (43 Kbytes). No guarantees....... Just tested under the Dev-C++/MingW port of the GNU compiler and under DOS/DJGPP, although I also expect it to work on other Intel-based i86 platforms. Now with a HTML version of the clwp manual.

For Microsoft Visual C 6 the assembler syntax is different, and the 1.3 download is not directly suitable, however Ade Adewole in Canada send me this adapted version of CLWP 1.1 (35 KB). Thanks!

There is also a port of CLWP13 to 16-bit Real-Mode DOS using Borland C++ v3.1 available, thanks to Muhammad Hasnain who took great effort to rewrite CLWP for this purpose. The whole source now uses near and especially far pointers extensively. All memory models except Huge are supported. Mind that 'proc()' is far and it takes a far 'param' (not needed if you are using Large Memory Model because far is default). Note: It is not a true 16-bit port because extended registers and instructions of 80386 are used. 16-bit is applicable to memory addressing mode only.

A small example of the use of CLWP:

#include "clwp.h"
#include <stdio.h>

#define MAX_PROC 3


void proc(void *param)         /* this proc will be started as thread */
{   while(1)                   /* multiple times in parallel */
    {   printf("PROC %d\n", *((int *) param) );
        clwpYield();           /* switch to next thread */
    }
}

int main()
{
    volatile int i;
    int ids[MAX_PROC];         /* to store thread IDs */
    int a=1, b=2, c=3;         /* 'data' for each thread */
    printf("\nCLWP Example.\n");
    printf("This program spawns 3 threads that each print messages.\n");
    fflush(stdout);

    if(clwpInit(1))            /* initialise the threading system */
    {                          /* and create 3 extra threads */
       ids[0] = clwpSpawn(proc, &a, 4096, 1, TRUE);
       ids[1] = clwpSpawn(proc, &b, 4096, 1, TRUE);
       ids[
2] = clwpSpawn(proc, &c, 4096, 1, TRUE);
       for(i=0;i<5;i++)        /* go looping, activating all threads */
       {
           printf("MAIN\n"); clwpYield();
       }

       clwpKill(ids[0]);       /* OK, work is done, let's go home */
       clwpKill(ids[1]);
       clwpKill(ids[2]);
   }
   printf("Ready\n");
   return(0);                  /* clwpExit call not needed (auto) */
}

/* end of file */

Doesn't this look simple? Off course does CLWP support more functionality, like semaphores, thread halt/resume, timed delay, and so on. Speed is quite high, using a simple timing reveiled that switching a thread takes about the same time as a function call (for more data, see the clwp manual in the zip file). So no reason anymore not to take a thread-based approach, many problems let code themselves much more easily this way.


Alternatives

pthreads

My first attempt: I expect also Wndows has some support for multi-threading. However, I like working to a more general standard, as to make it easier to port my programs to other platformsso I liked the POSIX standard implementation. You can find a version of the pthreads library suitable for Dev-C++/MingW at http://sources.redhat.com/pthreads-win32/ . Here the 800 Kbyte zipfile pthreads-2002-03-02.exe can be found, including full sources, tests, and so on where the test files also double as example files (or just take the precompiled library files at ftp://sources.redhat.com/pub/pthreads-win32/dll-latest). Compiled an ran out of the box! A definite yes if you are lokking for a pre-emptive threading package. Which I was not... For an introduction to POSIX threads look at the following site: Programming POSIX Threads

GNU pth

Also on the web is a good GNU implementation for co-operative multi-threading, GNU Pth. Looks great, however assumed a UNIX-like environment, like the Cygwin windows port. Especially the configuration program (checking the C compiler and library possibilities, like socket support) did expect a shell like the UNIX 'bash' shell (as delivered for Windows by Cygwin), and did not run under the more windows-based MingW port of the GNU compiler.

At my office indeed I do have the Cygnus port, and there it compiled and ran without problems. However, in that case I would also always deliver the cygwin dll runtime library with my programs, which I find way too large.

So I had to try by myself....