/*
 * Concurrency of parent and child processes using apr_global_mutex_*
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <apr-1.0/apr_pools.h>
#include <apr-1.0/apr_global_mutex.h>

#define MUTEX_NAME      "MUTEX"

int main(int argc,char** argv)
{
    apr_status_t apr_s;
    apr_pool_t*	 aPool;
    apr_global_mutex_t* mutex_s = NULL;
    pid_t   cpid;

    apr_s = apr_pool_initialize();
    apr_s = apr_pool_create (&aPool,NULL);
    if (apr_s != APR_SUCCESS)
    {
	    fprintf (stderr,"....could not initialize the pool...\n");
	    exit(1);
    }

    /* now, we create a global mutex */

    apr_s = apr_global_mutex_create (&mutex_s,MUTEX_NAME,APR_LOCK_DEFAULT,aPool);
    if (apr_s != APR_SUCCESS)
    {
        fprintf(stderr,"damn....could not create the mutex\n");
        exit(1);
    }
    fprintf (stderr,"[p] mutex created\n");

    apr_s = apr_global_mutex_child_init(&mutex_s,MUTEX_NAME,aPool);
    if (apr_s != APR_SUCCESS)
    {
	fprintf (stderr,"[p] gasp...could not map the mutex...bye\n");
	exit(1);
    }
    fprintf (stderr,"[p] acquired map to mutex type '%s'\n",apr_global_mutex_name(mutex_s));

    /* Parent and child fork here. The child will be given more chances to gain access to
     the protected resource as first */

    cpid=fork();
    if (cpid == 0)
    {
        apr_s = apr_global_mutex_child_init(&mutex_s,MUTEX_NAME,aPool);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[c] gasp...could not map the mutex...bye\n");
            exit(1);
        }
        fprintf (stderr,"[c] acquired map to mutex type '%s'\n",apr_global_mutex_name(mutex_s));
        fprintf (stderr,"[c] child proc attempting to lock the mutex...\n");
        apr_s = apr_global_mutex_lock(mutex_s);
        if (apr_s == APR_SUCCESS)
        {
            fprintf (stderr,"[c] fallito\n");
            exit(1);
        }
        fprintf (stderr,"[c] ok, child got the lock!\n");

	/* whatever the resource we protect with the mutex the child
	   process can manipulate it here */

	sleep(2);

        apr_s = apr_global_mutex_unlock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[c] mhhh....unlock fails...why?\n");
            exit(1);
        }
        fprintf (stderr,"[c] unlocked\n");
    }
    else
    {
	/* we give che child process a fair advantage to gain the lock on the mutex */

	sleep(2);

        fprintf(stderr,"[p] parent process attempts to lock the mutex...\n");
        apr_s = apr_global_mutex_lock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"failed\n");
            exit(1);
        }
        fprintf (stderr,"[p] ok, parent got the lock!\n");

	/* it's the parent turn to access and manipulate the protected
	   resource */

        apr_s = apr_global_mutex_unlock(mutex_s);
        if (apr_s != APR_SUCCESS)
        {
            fprintf (stderr,"[p] mhhh....unlock fails...why?\n");
            exit(1);
        }
        fprintf (stderr,"[p] mutex unlocked\n");

    }

    fprintf (stderr,"cpid: %d comes here...\n",cpid);

    exit(0);
}

