mirror of
				https://gitlab.com/klmp200/LO41.git
				synced 2025-11-04 11:13:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			173 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
//
 | 
						|
// 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; i<ELEVATOR_NB; i++) {
 | 
						|
				this->start_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; i<this->threads_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; i<this->threads_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;
 | 
						|
}
 |