#include <assert.h>
#include <pthread.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define WRITE_STRING(str) write(STDOUT_FILENO, str "\n", sizeof(str))
sem_t *food_sem; // Imagine this protects access to a gormet buffet
void *
hungry_thread(void *arg)
{
(void) arg;
for (;;) {
sem_wait(food_sem);
WRITE_STRING("I am the hungry thread, eating...");
sem_post(food_sem);
usleep(10000); // wait for 10ms
}
}
void *
greedy_thread(void *arg)
{
(void) arg;
for (;;) {
sem_wait(food_sem);
WRITE_STRING("I am the greedy thread, eating...");
usleep(10000); // wait for 10ms
sem_post(food_sem);
}
}
static
const char *FOOD_SEM_NAME = "buffet-table";
int
main()
{
pthread_t greedy_id, hungry_id;
int err;
sem_unlink(FOOD_SEM_NAME);
food_sem = sem_open(FOOD_SEM_NAME, O_CREAT, 0600, 1);
sem_unlink(FOOD_SEM_NAME);
if (food_sem == (sem_t *) SEM_FAILED) {
perror("sem_open failed");
exit(1);
}
err = pthread_create(&greedy_id, NULL, greedy_thread, NULL);
assert(err == 0);
err = pthread_create(&hungry_id, NULL, hungry_thread, NULL);
assert(err == 0);
WRITE_STRING("Threads created, parent sleeping...");
usleep(2000000); // wait for two seconds for experiment to run
WRITE_STRING("Parent waking up, stopping experiment...");
pthread_cancel(hungry_id);
pthread_cancel(greedy_id);
pthread_join(hungry_id, NULL);
pthread_join(greedy_id, NULL);
sem_close(food_sem);
WRITE_STRING("Threads joined, parent exiting...");
return 0;
}