/***********************************************************
 * mutex.c                                                 *
 * demonstration for a mutex solution to problem           *
 * Verteilte Systeme II Kapitel 6                          *
 ***********************************************************
 * 1998 by Frank Kargl (frank.kargl@rz.uni-ulm.de)         *
 ***********************************************************
 * Usage: problem                                          *
 ***********************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>

/* needed for multithreaded programming */
#define _REENTRANT

int counter = 0;			/* global counter */
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
					/* mutex for synchronization */

/***********************************************************
 *                                                         *
 * Function:                                               *
 * void *do_calc( void *arg )                              *
 * do some more or less sensefull calculation and          *
 * adjust counter in a safe way                            *
 * Parameters:                                             * 
 *  arg - number of incarnation                            *
 * Return:                                                 *
 *  always NULL                                            *
 *                                                         *
 ***********************************************************/

void *do_calc( void *arg ) {
    
    int i,j, tmpcount;
    double k;
    int intarg;

    /* convert argument */
    intarg = *(int *)arg;

    /* calculate 5 times */
    for( i=1; i<=5; i++ ) {
	printf("Calculating for arg = %d\n", intarg);
	fflush(stdout);
	/* lock mutex */
	pthread_mutex_lock(&mutex);
	tmpcount = counter;
	sleep(1);
	for (j=0; j<=1000; j++) {
	    k = i*j * sqrt(2);
	}
	tmpcount++;
	counter = tmpcount;
	/* unlock mutex */
	pthread_mutex_unlock(&mutex);
    }
    
    return NULL;

}

int main() {

    int ret;
    int arg1 = 1, arg2 = 2;

    pthread_t thread1, thread2;
    
    /* create 2 threads */
    ret = pthread_create( &thread1, NULL, do_calc, (void *) &arg1 );
    if( ret != 0 ) {
	fprintf(stderr, "Thread creation error\n");
    }
    ret = pthread_create( &thread1, NULL, do_calc, (void *) &arg2 );
    if( ret != 0 ) {
	fprintf(stderr, "Thread creation error\n");
    }
   
    /* wait for threads to finish */
    pthread_join( thread1, NULL );
    pthread_join( thread2, NULL );
    
    /* what´s the count, man ? */
    printf("count = %d\n", counter);
    
    return 0;
    
}
