/************************************************************** File: red_barrier.cc Description: A program that implements a barrier using a conditional variable from the pthread library. Author: Dana Vrajitoru Organization: IUSB, Computer and Information Sciences Date: September 2020 ***************************************************************/ #include #include #include #include using namespace std; #include "red_barrier.h" // global variables int no_ships; int counter = 0, global_id = 0; pthread_mutex_t id_mutex, barrier_mutex, cout_mutex; pthread_cond_t allin_cond; // Creates the threads calling the Ship_check_in function. void Create_threads(pthread_t *threads, int no_threads) { for (int i=0; i> no_ships; no_threads = no_ships; } // A barrier function based on the number of threads implemented using // a conditional variable. It uses a global counter intialized as // 0. Each thread coming in increments the counter. If the count is // not equal to the number of threads, it goes into a wait on the // conditional variable. The thread that finds the counter equal to // the number of threads broadcasts the condition that releases all of // them. void Barrier(int no_threads) { static int count = 0; pthread_mutex_lock(&barrier_mutex); count++; if (count == no_threads) { pthread_cond_broadcast(&allin_cond); // last one in lets everyone go count = 0; } else pthread_cond_wait(&allin_cond, &barrier_mutex); pthread_mutex_unlock(&barrier_mutex); } // The thread function: gets an id number, prints a message, calls the // barrier, prints a second message. The purpose is to see if the // messages printed by all the threads before the barrier are // separated from the one printed by the threads after the barrier. void *Ship_check_in(void *arg) { int id; Get_id(id); // Message before the barrier pthread_mutex_lock(&cout_mutex); cout << "Red " << id << " checking in" << endl; pthread_mutex_unlock(&cout_mutex); Barrier(no_ships); Wait(1000); // wait one second // Message after the barrier pthread_mutex_lock(&cout_mutex); cout << "Red " << id << " standing by" << endl; pthread_mutex_unlock(&cout_mutex); return NULL; } // Copies the value of a global id into the reference parameter and // increments the global id. void Get_id(int &id) { pthread_mutex_lock(&id_mutex); id = global_id; global_id++; pthread_mutex_unlock(&id_mutex); } // Waits for a given delay specified in miliseconds. void Wait(int delay) { struct timeval before, after; int timing = 0; gettimeofday(&before, 0); while (timing < delay) { gettimeofday(&after, 0); // Add the difference in seconds * 1000 and difference // in microseconds divided by 1000 timing = (after.tv_sec - before.tv_sec)*1000 + (after.tv_usec - before.tv_usec)/1000; } }