// // Created by Antoine Bartuccio on 06/06/2018. // #include "SharedData.h" GETTER(SharedData, Building *, main_building) SETTER(SharedData, Building *, main_building) int call_elevator_SharedData(THIS(SharedData), int starting_floor, int destination_floor){ /* Make the thread wait for an elevator available and return the id of the elevator available */ if (this->main_building == NULL) { CRASH("No building attached to shared data, you cannot call an elevator\n"); } if (starting_floor < 0) { CRASH("You cannot start from a floor lower than 0\n"); } if (destination_floor > FLOORS) { CRASH("You are trying to reach a floor higher than the highest floor\n"); } return 0; } void start_thread_SharedData(THIS(SharedData), void * (*thread)(void *), void * data, int thread_number){ pthread_create(this->threads[thread_number], 0, thread, data); } void start_all_threads_SharedData(THIS(SharedData)){ int i = 0; Element * current = NULL; List * residents = NULL; List * visitors = NULL; if (this->threads == NULL){ if (this->main_building == NULL) { CRASH("No building attached to SharedData and thus no thread can be created\n"); } else { residents = this->main_building->residents; visitors = this->main_building->visitors; this->threads_nb = residents->get_size(residents) + visitors->get_size(visitors) + ELEVATOR_NB; this->threads = malloc_or_die(sizeof(pthread_t*) * this->threads_nb); for (i=0; i < this->threads_nb; i++) this->threads[i] = malloc_or_die(sizeof(pthread_t)); pthread_mutex_lock(&this->mutex_active_passengers); pthread_mutex_lock(&this->mutex_threads); /* starting the elevator breaker */ this->start_thread(this, this->elevator_breaker->runnable, this->elevator_breaker, 0); this->elevator_breaker->set_thread_number(this->elevator_breaker, 0); /* starts threading elevators */ for (i=1; istart_thread(this, this->main_building->elevators[i]->runnable, this->main_building->elevators[i], i); this->main_building->elevators[i]->set_thread_number(this->main_building->elevators[i], i); } /* starts threading visitors */ current = visitors->get_head(visitors); while (current != NULL){ this->start_thread(this, ((Visitor*)current->get_data(current))->runnable, current->get_data(current), i); ((Visitor*)current->get_data(current))->set_thread_number((Visitor*)current->get_data(current), i); current = current->get_next(current); this->active_passengers++; i++; } /* starts threading residents */ current = residents->get_head(residents); while (current != NULL){ this->start_thread(this, ((Resident*)current->get_data(current))->runnable, current->get_data(current), i); ((Resident*)current->get_data(current))->set_thread_number((Resident*)current->get_data(current), i); current = current->get_next(current); this->active_passengers++; i++; } pthread_mutex_unlock(&this->mutex_threads); pthread_mutex_unlock(&this->mutex_active_passengers); } } } void wait_all_threads_SharedData(THIS(SharedData)){ int i; for (i=0; ithreads_nb; i++) { if (this->threads[i] != NULL) pthread_join(*this->threads[i], NULL); } } int use_call_box_SharedData(THIS(SharedData), char * resident_name){ return this->main_building->use_call_box(this->main_building, resident_name); } void _free__SharedData(THIS(SharedData)){ int i; if (this->threads != NULL){ for (i=0; ithreads_nb; i++) { if (this->threads[i] != NULL) { printf("Quitting thread %d\n", (*(int*) this->threads[i])); pthread_kill(*this->threads[i], SIGUSR1); free(this->threads[i]); } } free(this->threads); } if (this->main_building != NULL) DELETE(this->main_building); DELETE(this->elevator_breaker); pthread_mutex_unlock(&this->mutex_active_passengers); pthread_mutex_destroy(&this->mutex_active_passengers); pthread_mutex_unlock(&this->mutex_threads); pthread_mutex_destroy(&this->mutex_threads); free(this); } int is_active_passengers_left_SharedData(THIS(SharedData)){ int response; pthread_mutex_lock(&this->mutex_active_passengers); response = (this->active_passengers > 0); pthread_mutex_unlock(&this->mutex_active_passengers); return response; } void decrement_active_passengers_SharedData(THIS(SharedData)){ pthread_mutex_lock(&this->mutex_active_passengers); this->active_passengers--; pthread_mutex_unlock(&this->mutex_active_passengers); } void unregister_thread_SharedData(THIS(SharedData), int thread_number){ pthread_mutex_lock(&this->mutex_threads); free(this->threads[thread_number]); this->threads[thread_number] = NULL; pthread_mutex_unlock(&this->mutex_threads); } SharedData *_get_instance_SharedData(){ static SharedData * new_shared_data = NULL; if (new_shared_data == NULL){ new_shared_data = malloc_or_die(sizeof(SharedData)); new_shared_data->threads = NULL; new_shared_data->main_building = NULL; /* Should be set to NULL if freed before */ new_shared_data->threads_nb = 0; new_shared_data->active_passengers = 0; new_shared_data->elevator_breaker = NEW(ElevatorBreaker); pthread_mutex_init(&new_shared_data->mutex_active_passengers, NULL); pthread_mutex_init(&new_shared_data->mutex_threads, NULL); LINK_ALL(SharedData, new_shared_data, start_thread, start_all_threads, wait_all_threads, set_main_building, get_main_building, use_call_box, call_elevator, decrement_active_passengers, is_active_passengers_left, unregister_thread ); } return new_shared_data; }