// // Created by Antoine Bartuccio on 05/06/2018. // #include #include "Building.h" #include "../Resident/Resident.h" #include "../Visitor/Visitor.h" #define LINE_BUFFER 256 void remove_end_char(char * string, char character){ size_t string_size = strlen(string); if (string[string_size - 1] == character) string[string_size - 1] = '\0'; } List * split(char * line, char * separator){ List * split = NEW(List); char * to_delete = strdup(line); char * to_delete_back = to_delete; char * token = NULL; while((token = strsep(&to_delete, separator)) != NULL) split->insert_tail(split, (void*) token, sizeof(char) * strlen(token)); free(to_delete_back); return split; } void parse_residents_Building(THIS(Building), char * file){ /* File format is name;appartment_floor;destination */ FILE * f = fopen(file, "r"); List * line_split = NULL; Resident * resident = NULL; size_t len = LINE_BUFFER; char * line = NULL; char * trash; int i = 0; if (f == NULL) { CRASH("File for residents does not exist"); } while (getline(&line, &len, f) > 0) { remove_end_char(line, '\n'); line_split = split(line, ";"); resident = NEW(Resident, i, line_split->get_element_data(line_split, 0), (int) strtol(line_split->get_element_data(line_split, 1), &trash, 10), (int) strtol(line_split->get_element_data(line_split, 2), &trash, 10)); this->residents->insert_tail(this->residents, resident, sizeof(Resident)); resident->name = NULL; DELETE(resident); DELETE(line_split); i++; } free(line); fclose(f); } void parse_visitors_Building(THIS(Building), char * file){ /* File format is name;contact_name */ FILE * f = fopen(file, "r"); List * line_split = NULL; Visitor * visitor = NULL; size_t len = LINE_BUFFER; char * line = NULL; int i = 0; if (f == NULL) { CRASH("File for visitors does not exist"); } while (getline(&line, &len, f) > 0) { remove_end_char(line, '\n'); line_split = split(line, ";"); visitor = NEW(Visitor, i, line_split->get_element_data(line_split, 0), line_split->get_element_data(line_split, 1)); this->visitors->insert_tail(this->visitors, visitor, sizeof(Visitor)); visitor->contact_name = NULL; visitor->name = NULL; DELETE(visitor); DELETE(line_split); i++; } free(line); fclose(f); } void free_resident(void* data){ Resident * r = (Resident *) data; DELETE(r); } void free_visitor(void* data){ Visitor * v = (Visitor *) data; DELETE(v); } void _free__Building(THIS(Building)){ int i = 0; this->residents->clear_custom(this->residents, free_resident); this->visitors->clear_custom(this->visitors, free_visitor); pthread_mutex_unlock(this->mutex_cond_get_inside_elevator); pthread_mutex_destroy(this->mutex_cond_get_inside_elevator); pthread_mutex_unlock(this->mutex_cond_get_outside_elevator); pthread_mutex_destroy(this->mutex_cond_get_outside_elevator); pthread_mutex_unlock(this->mutex_func_get_inside_elevator); pthread_mutex_destroy(this->mutex_func_get_inside_elevator); DELETE(this->residents); DELETE(this->visitors); for (i=0; ielevators[i]); for (i=0; icondition_floors[i]); free(this->condition_floors[i]); } free(this->condition_floors); free(this->mutex_cond_get_inside_elevator); free(this->mutex_cond_get_outside_elevator); free(this->mutex_func_get_inside_elevator); free(this->elevators); free(this); } int get_inside_elevator_Building(THIS(Building), int current_floor, ElevatorPassenger elevator_passenger){ int i; /* Make assumption that a waiting elevator is not full */ pthread_mutex_lock(this->mutex_func_get_inside_elevator); printf("Test d'entrée à l'étage %d de %s : id %d\n", current_floor, elevator_passenger.passenger.visitor->name, elevator_passenger.passenger.visitor->id); for (i=0; ielevators[i]->can_get_inside(this->elevators[i], current_floor)){ /* pour faire taire le compilateur le temps que je revienne sur cette fonction */ if (elevator_passenger.type == VISITOR) this->elevators[i]->add_passenger(this->elevators[i], elevator_passenger); /* Il faut faire des trucs ici */ pthread_mutex_unlock(this->mutex_func_get_inside_elevator); return i; } } pthread_mutex_unlock(this->mutex_func_get_inside_elevator); return -1; } void go_to_floor_Building(THIS(Building), int origin, int destination, ElevatorPassenger elevator_passenger){ int elevator_number; if (origin < 0 || origin >= FLOORS) {CRASH("You are trying to start from a non existing floor\n");} if (destination < 0 || destination >= FLOORS) {CRASH("You are trying to reach a non existing floor\n");} pthread_cond_wait(this->condition_floors[origin], this->mutex_cond_get_inside_elevator); elevator_number = this->get_inside_elevator(this, origin, elevator_passenger); if (elevator_passenger.type == RESIDENT) printf("Le résident %s rentre dans l'ascenseur %s depuis l'étage %d\n", elevator_passenger.passenger.resident->name, this->elevators[elevator_number]->name, origin); else if (elevator_passenger.type == VISITOR) printf("Le visiteur %s rentre dans l'ascenseur %s depuis l'étage %d\n", elevator_passenger.passenger.visitor->name, this->elevators[elevator_number]->name, origin); pthread_cond_wait(this->condition_floors[destination], this->mutex_cond_get_outside_elevator); if (elevator_passenger.type == RESIDENT) printf("Le résident %s sors de l'ascenseur %s à l'étage %d\n", elevator_passenger.passenger.resident->name, this->elevators[elevator_number]->name, destination); else if (elevator_passenger.type == VISITOR) printf("Le visiteur %s sors de l'ascenseur %s à l'étage %d\n", elevator_passenger.passenger.visitor->name, this->elevators[elevator_number]->name, destination); } int use_call_box_Building(THIS(Building), char * resident_name){ /* Return negative number if not found */ Element * current = this->residents->get_head(this->residents); while (current != NULL){ if (!strcmp(((Resident *) current->get_data(current))->name, resident_name)) return ((Resident *) current->get_data(current))->apartment_floor; current = current->get_next(current); } return -1; } void signal_elevator_at_floor_Building(THIS(Building), int floor){ pthread_cond_signal(this->condition_floors[floor]); } Building *_init_Building(char * residents_file, char * visitors_file){ Building * new_building = malloc_or_die(sizeof(Building)); char elevator_name[] = "@"; int i; new_building->floors = FLOORS; new_building->elevators = malloc_or_die(sizeof(Elevator*) * ELEVATOR_NB); new_building->mutex_cond_get_inside_elevator = malloc_or_die(sizeof(pthread_mutex_t)); new_building->mutex_cond_get_outside_elevator = malloc_or_die(sizeof(pthread_mutex_t)); new_building->mutex_func_get_inside_elevator = malloc_or_die(sizeof(pthread_mutex_t)); pthread_mutex_init(new_building->mutex_cond_get_inside_elevator, NULL); pthread_mutex_init(new_building->mutex_cond_get_outside_elevator, NULL); pthread_mutex_init(new_building->mutex_func_get_inside_elevator, NULL); new_building->condition_floors = malloc_or_die(sizeof(pthread_cond_t*) * FLOORS); new_building->residents = NEW(List); new_building->visitors = NEW(List); for (i=0; ielevators[i] = NEW(Elevator, elevator_name); } for (i=0; icondition_floors[i] = malloc_or_die((sizeof(pthread_cond_t))); pthread_cond_init(new_building->condition_floors[i], NULL); } LINK_ALL(Building, new_building, parse_residents, parse_visitors, get_inside_elevator, use_call_box, go_to_floor, signal_elevator_at_floor ) if (residents_file != NULL) new_building->parse_residents(new_building, residents_file); if (visitors_file != NULL) new_building->parse_visitors(new_building, visitors_file); return new_building; }