+#include "barrier.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "barrier.c"
+
+/**
+ * @file test_barrier.c
+ * @purpose Test the barrier!
+ * @author Sam Moore (20503628) 2012
+ */
+
+// Compile with gcc --std=c99 -o test_barrier test_barrier.c -lpthread
+// Run with ./test_barrier
+// Expected output:
+// All worker threads print "Hello" before all worker threads print "Goodbye"
+// At any point, the "Boss" reports that it is waiting for "Hello" to be said, and goes to sleep.
+// At some point whilst worker threads say "Goodbye", the "Boss" wakes up and reports that "Hello" has been said.
+// The Boss should *never* report that "Hello" has been said until all workers say "Hello".
+// But it may report that it is waiting for "Hello" to be said at any time.
+// Confused yet? I am, and I wrote this!
+// NOTE: Two barriers are required to prevent deadlocking!
+
+
+pthread_mutex_t mutex_printf; // Printing is not thread safe! Mutex needed!
+Barrier worker_barrier[2];
+
+void * Worker(void * args)
+{
+
+ //while (true) // Comment out to only test one step
+ {
+ Barrier_Enter(&worker_barrier[0]); // Workers are now printing "Hello"
+
+ pthread_mutex_lock(&mutex_printf);
+ printf("Worker %p: Hello\n", (args)); // Only one thread can print at a time
+ pthread_mutex_unlock(&mutex_printf);
+
+ sleep(1);
+ Barrier_Join(&worker_barrier[0]);
+
+ pthread_mutex_lock(&mutex_printf);
+ printf("\tWorker %p: Goodbye\n", (args)); // Only one thread can print at a time
+ pthread_mutex_unlock(&mutex_printf);
+
+
+ Barrier_Join(&worker_barrier[1]); // If we replace this with:
+ //Barrier_Join(&worker_barrier[0]);
+ // Then there is (usually) a deadlock, because the first thread to leave the barrier
+ // immediately reactivates it, and other threads are unable to leave.
+
+ }
+}
+
+void * Boss(void * args)
+{
+ //while (true)
+ {
+ pthread_mutex_lock(&mutex_printf);
+ printf("Boss is waiting for \"Hello\" to be said.\n", (args)); // Only one thread can print at a time
+ pthread_mutex_unlock(&mutex_printf);
+ Barrier_Wait(&worker_barrier[0]);
+ pthread_mutex_lock(&mutex_printf);
+ printf("Boss continues now that workers have said \"Hello\".\n", (args)); // Only one thread can print at a time
+ pthread_mutex_unlock(&mutex_printf);
+ sleep(2);
+
+ }
+}
+
+int main(int argc, char ** argv)
+{
+ #define NUM_THREADS 4
+ pthread_t worker[NUM_THREADS];
+ pthread_t boss;
+
+ Barrier_Init(&worker_barrier[0], NUM_THREADS); // Initialise barriers with number of contributing threads
+ Barrier_Init(&worker_barrier[1], NUM_THREADS);
+
+ pthread_create(&boss, NULL, Boss, NULL); //Start boss
+
+ for (long i = 0; i < NUM_THREADS; ++i)
+ pthread_create(worker+i, NULL, Worker, (void*)(i)); // Start all threads
+
+ for (int i = 0; i < NUM_THREADS; ++i) // Join threads
+ pthread_join(worker[i], NULL);
+ return 0;
+}