#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <semaphore.h>

#include "mythreads.h"

int max;
int loops;
int *buffer; // have to allocate space

int useptr  = 0;
int fillptr = 0;
#define CMAX (1000)
int consumers = 1;

int verbose = 1;

void do_fill(int value) 
{
    buffer[fillptr] = value;
    fillptr = (fillptr + 1) % max;
}

int do_get()
{
    int tmp = buffer[useptr];
    useptr = (useptr + 1) % max;
    return tmp;
}

void *
producer(void *arg)
{
    int i;
    for (i = 0; i < loops; i++) {
        do_fill(i); 
    }

    // end case
    for (i = 0; i < consumers; i++) {
        do_fill(-1);
    }

    return NULL;
}
                                                                               
void *
consumer(void *arg)
{
    int tmp = 0;
    while (tmp != -1) { // end case
        tmp = do_get(); 
        if (verbose && tmp != -1)
            printf("%d: %d\n", (int)arg, tmp);
    }
    return NULL;
}

int
main(int argc, char *argv[])
{
    if (argc != 4) {
        fprintf(stderr, "usage: %s <buffersize> <loops> <consumers>\n", argv[0]);
        exit(1);
    }
    max   = atoi(argv[1]);
    loops = atoi(argv[2]);
    consumers = atoi(argv[3]);
    assert(consumers <= CMAX);

    buffer = (int *) Malloc(max * sizeof(int));
    int i;
    for (i = 0; i < max; i++) {
        buffer[i] = 0;
    }

    pthread_t pid, cid[CMAX];
    Pthread_create(&pid, NULL, producer, NULL); 
    for (i = 0; i < consumers; i++) {
        Pthread_create(&cid[i], NULL, consumer, (void *)((uint64_t)i)); 
    }

    Pthread_join(pid, NULL); 
    for (i = 0; i < consumers; i++) {
        Pthread_join(cid[i], NULL); 
    }
    return 0;
}

