web page updated Wednesday 11th February 2004 930pm
=========== new developments ===========
(930pm.wed.11.feb.2004) I have written an example threaded graphics program, click to download it, compile it as explained for rhyme.c below.
For further info see here
========================================
Download the example rhyme.c, and 2 binaries rhyme and rhyme_noyield.
This example *can* be run from the AmigaOS shell,
======= How to compile rhyme.c, untidy method =============
This is how you compile it if Pth-2.0.0 is not integrated into your Geek setup. Lets say Pth-2.0.0-amiga-bin.tar.gz is decompressed to xyz:
gcc -Ixyz:local/include -m68020 -c rhyme.c -o rhyme.o gcc -o rhyme rhyme.o xyz:local/lib/libpthread020.a
That's it!
====== How to compile rhyme.c, better method =============
This method is if you have decompressed Pth-2.0.0 directly into gg:
gcc -m68020 -c rhyme.c -o rhyme.o gcc -o rhyme rhyme.o -lpthread020
For a 68000 compile, put -m68000 instead of -m68020, and -lpthread instead of -lpthread020. Strictly speaking libpthread020.a should be called libm020/libpthread.a, but I found gcc ignored it when I did this.
==============================================
Please only use the current libpth and libpthread in no FPU compiles, as I am not convinced it saves FPU context. Probably keep to 68000 no fpu and 68020 no fpu usage. Possibly an FPU compile *must* use an FPU version of ixemul.library otherwise bad FPU context change.
Compiling for pth is exactly the same, just replace the substring pthread by pth in the above explanation.
The program looks like this:
#include <pthread.h> #include <stdio.h> char *x[]= { "hickory dickory dock, " , "the mouse ran up the clock, " , "the clock struck one, " , "the mouse ran down, " , "hickory dickory dock. " } ; int number = 5 ; int count = 3 ; void *thread_function(void *arg) { int i , num ; num = (int)arg ; for (i = 0; i < count ; i++) { write( 1 , x[ num ] , strlen( x[num] ) ) ; pthread_yield_np(); sleep(1); } return( 0 ) ; } int main( int argc , char **argv ) { pthread_t thread; int i ; for(i = 0; i < number ; i++) { if (pthread_create(&thread, NULL, thread_function , (void *) i)) printf("failed to create thread %d\n", i); pthread_yield_np(); } pthread_exit( 0 ) ; }
Commentary:
pthread.h
needs to be the first #include as it may contain
hacks. For pth I think pth.h
is the last #include, so
pthread.h
is first, pth.h
is last. Dont forget!
To understand the purpose of the pthread_yield_np();
statements,
comment them out to generate rhyme_noyield.
To understand the point of the pthread_exit(0);
call,
try removing it *and* both the pthread_yield_np()
calls.
The program does nothing, this is because it generates the threads and
never yields. pthread_exit(0);
is a synchronisation statement:
it waits for all the threads to complete and then exits the program.
Without it the program would instantly exit not waiting for the threads
to complete.
write()
is used instead of printf()
as
write()
doesnt wait till newline before echoing the text.
Different threads can have different thread functions.
The 4th argument of pthread_create
is passed to the 3rd argument
of pthread_create
, ie in the above the thread is begun as:
thread_function((void *)i);
. So the 4th argument is user private
data for the thread eg so the thread can identify itself (several threads
may be using the same function).
The very first line of main()
can optionally be
pthread_init();
The very last line of main()
can optionally be the
thread synchronisation statement pthread_exit(0 );
explained
above.
With Pth-2.0.0 ported unmodified, pthread_exit(0);
was causing a
recoverable alert, anyway this is fixed. You can see from the above that
this call is quite necessary. You can also see from the above that
some strange bugs could happen if you arent careful. With tasks and threads
you have to proceed very carefully.