- Introduction
- Mandatory Part
- Code Overview
- Organization and Task Distribution
- Execution Breakdown
- Feedback
The Philosopher project simulates the dining philosophers problem, a classic synchronization problem used to illustrate the challenges of resource allocation among concurrent processes. This project uses threads and mutexes to manage the philosophers' actions of eating, thinking, and sleeping while preventing deadlocks and ensuring that no philosopher starves.
Your Philosopher project must implement the following features:
- Each philosopher is represented by a thread.
- Philosophers must alternate between eating, thinking, and sleeping.
- There are as many forks as philosophers, and each philosopher needs two forks to eat.
- Philosophers must pick up the forks one at a time.
- Philosophers must put down both forks after eating and before sleeping.
- Philosophers must not die of starvation.
- All state changes of the philosophers (eating, thinking, sleeping, taking a fork, and dying) must be logged with a timestamp.
- The simulation stops if a philosopher dies.
The parsing part of the Philosopher project includes the following files:
philo_parsing.c
: Functions to parse command line arguments and initialize the simulation parameters.
The memory management part of the Philosopher project includes the following files:
philo_memory_allocation.c
: Functions to allocate memory for the philosopher structures and other resources.philo_memory_liberation.c
: Functions to free the allocated memory and ensure no memory leaks.
The action handling part of the Philosopher project includes the following files:
philo_actions.c
: Functions that define the actions (eating, thinking, and sleeping) of each philosopher.philo_routine.c
: Functions that define the main routine for each philosopher thread.philo_survey_routine.c
: Functions that monitor the philosophers' states to detect and handle starvation.
The thread management part of the Philosopher project includes the following files:
philo_threads.c
: Functions to create, detach, and join philosopher threads.
The utility part of the Philosopher project includes the following files:
philo_utils.c
: Utility functions for handling time, printing logs, and other helper functions.philo_error_utils.c
: Utility functions for handling errors and printing error messages.philo_error.c
: Functions to handle error scenarios and clean up resources.
The main execution part of the Philosopher project includes the following file:
main.c
: The entry point of the program that initializes the simulation and starts the philosopher threads.
In our group, named "the brute and the cunning", we decided to clearly separate our responsibilities. I handled the memory management and action handling, while my partner focused on parsing and thread management. This clear division allowed us to work efficiently and integrate our parts smoothly.
For this project, I divided the execution into four main parts:
-
Memory Management:
Allocating and freeing memory efficiently to ensure no leaks occur during the simulation. This part was challenging due to the need to manage multiple dynamic allocations and deallocations.
-
Action Handling:
Defining the actions of eating, thinking, and sleeping for each philosopher. Ensuring that these actions are performed in the correct order and logged accurately.
-
Thread Management:
Creating and managing threads for each philosopher. Ensuring that threads are properly synchronized to avoid deadlocks and race conditions.
-
Error Handling:
Implementing robust error handling mechanisms to gracefully handle any unexpected scenarios. This included validating input parameters and ensuring proper cleanup of resources in case of errors.
The Philosopher project allows for the mastery of two essential concepts in low-level programming: threads and mutexes. Successfully completing this project primarily hinges on understanding and effectively utilizing these concepts.
For me, having previously worked on the Minishell project, I found this one relatively manageable. To challenge myself further, I focused on enhancing the readability of my code. Although I am not entirely satisfied with the final result, I noticed significant improvements in the syntax and formatting of my code during the writing process. Consequently, the amount of work required for bug fixing, compliance with standards, and code clarification was reduced for this project.
On a personal note, I truly enjoyed working on this project. I find the assignment particularly elegant as it allows for the tackling of a purely computational problem. Certain concepts addressed, such as the management of the timer originating from the creation of UNIX, require an understanding and assimilation of a part of the history of computer development.