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

#define CAPACITY 3
#define ITEM_COUNT 10

int buffer[CAPACITY];
int next_put = 0, next_get = 0, used = 0;
pthread_mutex_t lock;
pthread_cond_t not_empty, not_full;

void *produce(void *argument) {
    (void)argument;
    for (int item = 1; item <= ITEM_COUNT; item++) {
        pthread_mutex_lock(&lock);
        while (used == CAPACITY) {
            pthread_cond_wait(&not_full, &lock);
        }
        buffer[next_put] = item;
        next_put = (next_put + 1) % CAPACITY;
        used++;
        pthread_cond_signal(&not_empty);
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

void *consume(void *argument) {
    (void)argument;
    int sum = 0;
    for (int i = 0; i < ITEM_COUNT; i++) {
        pthread_mutex_lock(&lock);
        while (used == 0) {
            pthread_cond_wait(&not_empty, &lock);
        }
        int item = buffer[next_get];
        next_get = (next_get + 1) % CAPACITY;
        used--;
        pthread_cond_signal(&not_full);
        pthread_mutex_unlock(&lock);

        printf("Consumed: %d\n", item);
        sum += item;
    }
    printf("Sum: %d\n", sum);
    printf("Check: %s\n",
           sum == ITEM_COUNT * (ITEM_COUNT + 1) / 2 ? "PASS" : "FAIL");
    return NULL;
}

int main(void) {
    pthread_t producer, consumer;
    pthread_mutex_init(&lock, NULL);
    pthread_cond_init(&not_empty, NULL);
    pthread_cond_init(&not_full, NULL);
    pthread_create(&consumer, NULL, consume, NULL);
    pthread_create(&producer, NULL, produce, NULL);
    pthread_join(producer, NULL);
    pthread_join(consumer, NULL);
    pthread_cond_destroy(&not_empty);
    pthread_cond_destroy(&not_full);
    pthread_mutex_destroy(&lock);
    return 0;
}
