// From http://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.neutrino.getting_started/topic/s1_procs_condvar.html
/*
 * cp1.c
*/

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int data_ready = 0;
pthread_mutex_t mutex;
pthread_cond_t  condvar;

static void*
consumer (void *notused)
{
    printf ("In consumer thread...\n");
    while (1) {
        pthread_mutex_lock (&mutex);
        while (!data_ready) {
            pthread_cond_wait (&condvar, &mutex);
        }
        // process data
        printf ("consumer:  got data from producer\n");
        data_ready = 0;
        pthread_cond_signal (&condvar);
        pthread_mutex_unlock (&mutex);
    }
        
    puts("THREAD FUNCTION consumer EXITING (should be cancelled before?)");
    return notused;
}

void *
producer (void *notused)
{
    printf ("In producer thread...\n");
    while (1) {
        // get data from hardware
        // we'll simulate this with a sleep (1)
        sleep (100); // actually we will just sleep
        printf ("producer:  ? got data from h/w\n");
        pthread_mutex_lock (&mutex);
        while (data_ready) {
            pthread_cond_wait (&condvar, &mutex);
        }
        data_ready = 1;
        pthread_cond_signal (&condvar);
        pthread_mutex_unlock (&mutex);
    }
    puts("THREAD FUNCTION producer EXITING (should be cancelled before?)");
    return notused;
}

int main ()
{
    printf ("Starting consumer/producer example...\n");

    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
    pthread_mutex_init(&mutex, &attr);
    pthread_mutexattr_destroy(&attr);

    pthread_cond_init(&condvar, NULL);

    pthread_t tid1;
    pthread_t tid2;

    // create the producer and consumer threads
    pthread_create (&tid1, NULL, producer, NULL);
    pthread_create (&tid2, NULL, consumer, NULL);

    // let the threads run for a bit
    sleep (2);

    pthread_cancel(tid1);
    pthread_cancel(tid2);

    puts("Joining 1...");
    pthread_join(tid1, NULL);
    puts("Joining 2...");
    pthread_join(tid2, NULL); /* QNX blocks here */
    puts("Done.");
    return 0;
}
