📚 The CoCalc Library - books, templates and other resources
License: OTHER
/* Example code for Think OS.12Copyright 2015 Allen Downey3License: Creative Commons Attribution-ShareAlike 3.045*/67#include <stdio.h>8#include <stdlib.h>9#include <assert.h>10#include <pthread.h>11#include "utils.h"1213#define NUM_CHILDREN 214#define QUEUE_LENGTH 161516// QUEUE1718typedef struct {19int *array;20int length;21int next_in;22int next_out;23} Queue;2425Queue *make_queue(int length)26{27Queue *queue = (Queue *) malloc(sizeof(Queue));28queue->length = length;29queue->array = (int *) malloc(length * sizeof(int));30queue->next_in = 0;31queue->next_out = 0;32return queue;33}3435int queue_incr(Queue *queue, int i)36{37return (i+1) % queue->length;38}3940int queue_empty(Queue *queue)41{42// queue is empty if next_in and next_out are the same43return (queue->next_in == queue->next_out);44}4546int queue_full(Queue *queue)47{48// queue is full if incrementing next_in lands on next_out49return (queue_incr(queue, queue->next_in) == queue->next_out);50}5152void queue_push(Queue *queue, int item) {53if (queue_full(queue)) {54perror_exit("queue is full");55}5657queue->array[queue->next_in] = item;58queue->next_in = queue_incr(queue, queue->next_in);59}6061int queue_pop(Queue *queue) {62if (queue_empty(queue)) {63perror_exit("queue is empty");64}6566int item = queue->array[queue->next_out];67queue->next_out = queue_incr(queue, queue->next_out);68return item;69}7071// SHARED7273typedef struct {74Queue *queue;75} Shared;7677Shared *make_shared()78{79Shared *shared = check_malloc(sizeof(Shared));80shared->queue = make_queue(QUEUE_LENGTH);81return shared;82}8384// THREAD8586pthread_t make_thread(void *(*entry)(void *), Shared *shared)87{88int ret;89pthread_t thread;9091ret = pthread_create(&thread, NULL, entry, (void *) shared);92if (ret != 0) {93perror_exit("pthread_create failed");94}95return thread;96}9798void join_thread(pthread_t thread)99{100int ret = pthread_join(thread, NULL);101if (ret == -1) {102perror_exit("pthread_join failed");103}104}105106// PRODUCER-CONSUMER107108void *producer_entry(void *arg)109{110int i;111Shared *shared = (Shared *) arg;112for (i=0; i<QUEUE_LENGTH-1; i++) {113printf("adding item %d\n", i);114queue_push(shared->queue, i);115}116pthread_exit(NULL);117}118119void *consumer_entry(void *arg)120{121int i;122int item;123Shared *shared = (Shared *) arg;124125for (i=0; i<QUEUE_LENGTH-1; i++) {126item = queue_pop(shared->queue);127printf("consuming item %d\n", item);128}129pthread_exit(NULL);130}131132// TEST CODE133134void queue_test()135{136int i;137int item;138int length = 128;139140Queue *queue = make_queue(length);141assert(queue_empty(queue));142for (i=0; i<length-1; i++) {143queue_push(queue, i);144}145assert(queue_full(queue));146for (i=0; i<10; i++) {147item = queue_pop(queue);148assert(i == item);149}150assert(!queue_empty(queue));151assert(!queue_full(queue));152for (i=0; i<10; i++) {153queue_push(queue, i);154}155assert(queue_full(queue));156for (i=0; i<10; i++) {157item = queue_pop(queue);158}159assert(item == 19);160}161162int main()163{164int i;165pthread_t child[NUM_CHILDREN];166167Shared *shared = make_shared();168169child[0] = make_thread(producer_entry, shared);170child[1] = make_thread(consumer_entry, shared);171172for (i=0; i<NUM_CHILDREN; i++) {173join_thread(child[i]);174}175176return 0;177}178179180