This README provides an overview of the Philo project, detailing its objectives and offering guidance. The goal of the project is to implement a simulation of the classic Dining Philosophers problem in C, adhering to POSIX standards and best practices in multithreaded programming. It demonstrates synchronization techniques using POSIX threads (pthreads) and mutex locks to manage resource sharing among concurrent threads.
- Introduction
- Project Structure
- Installation and Compilation
- Running the Program
- Philo Features
- Examples
- Conclusion
Philo is a project designed to deepen your understanding of:
- Multithreading and Concurrency: Managing multiple threads using POSIX threads.
- Synchronization Mechanisms: Utilizing mutexes to prevent race conditions.
- Process Coordination: Simulating the Dining Philosophers problem to manage resource sharing.
- Argument Parsing and Validation: Handling user inputs robustly to ensure correct program behavior.
- Memory Management: Ensuring efficient use of memory and preventing leaks.
The primary objective is to create a simulation where philosophers alternately think, eat, and sleep, requiring the use of forks (represented by mutexes) to eat. This project emphasizes correct synchronization to avoid deadlocks and ensure that all philosophers can eventually eat.
Philo is organized into several key components:
- Main Program (
main.c
) – Initializes data structures, creates philosopher threads, and manages program termination. - Data Structures (
philosophers.h
) – Defines the core structures such ast_data
andt_philo
. - Utilities (
utils.c
) – Contains helper functions likeft_atoi
, argument validation, and time management. - Philosopher Routine (
philosopher_routine.c
) – Defines the behavior of each philosopher thread. - Initialization (
init.c
) – Handles the initialization of data structures and resources. - Makefile – Automates the build process, including compilation and cleanup tasks.
- Images (
imgs/
) – Contains visual representations or animations related to the project (e.g.,philo.gif
). - README.md – Provides documentation and guidance for users and contributors.
Follow these steps to build and set up the Philo project on your local machine:
Ensure you have the following installed:
- C Compiler: GCC or a compatible C compiler.
- POSIX-Compliant Environment: Linux or macOS.
- Make: To facilitate the build process.
Clone the repository to your local machine using Git:
git clone https://github.com/djelacik/Philosophers
cd philo
Build the Project Use the provided Makefile to compile the project:
make
This command will compile the necessary .c files and produce an executable named philo in the project directory.
Once successfully compiled, you can launch Philo by running:
./philo [number_of_philosophers] [time_to_die] [time_to_eat] [time_to_sleep] [optional: number_of_times_each_philosopher_must_eat]
Command-Line Arguments:
- Number of Philosophers: The total number of philosophers and forks.
- Time to Die (ms): Time (in milliseconds) a philosopher can live without eating.
- Time to Eat (ms): Time (in milliseconds) a philosopher spends eating.
- Time to Sleep (ms): Time (in milliseconds) a philosopher spends sleeping.
- Number of Times Each Philosopher Must Eat (optional): If all philosophers eat at least this many times, the simulation ends.
Example
./philo 5 2000 100 60
This command starts the simulation with five philosophers, each having 2000 ms to die without eating, 100 ms to eat, and 60 ms to sleep.
To specify the number of times each philosopher must eat:
./philo 5 2000 100 60 7
- Concurrent Philosophers: Each philosopher runs in its own thread, simulating parallel actions.
- POSIX Threads: Utilizes pthreads for efficient thread management.
- Fork Management: Forks are protected by mutexes to prevent simultaneous access.
- Deadlock Prevention: Implements strategies to avoid deadlocks, ensuring smooth simulation.
- Robust Input Handling: Ensures all command-line arguments are valid and within expected ranges.
- Clear Error Messages: Provides descriptive errors for invalid inputs.
- Thinking, Eating, Sleeping: Simulates the typical actions of philosophers with accurate timing.
- Time Management: Tracks and enforces time constraints for each action.
- Activity Logs: Records significant events like fork acquisition, eating, and sleeping.
- Thread-Safe Logging: Ensures logs are correctly synchronized across threads.
- Dynamic Allocation: Allocates resources based on the number of philosophers.
- Leak Prevention: Frees all allocated memory and destroys mutexes upon termination.
- Variable Philosophers: Supports different numbers of philosophers for customizable simulations.
- Optional Eating Count: Allows setting how many times each philosopher must eat before ending the simulation.
./philo 5 2000 100 60
Output:
[0 ms] Philosopher 1 has taken a fork.
[0 ms] Philosopher 1 is eating.
[0 ms] Philosopher 2 has taken a fork.
[0 ms] Philosopher 2 is eating.
...
./philo 5 2000 100 60 7
Output:
All philosophers have eaten at least 7 times. Simulation ends.
./philo -5 2000 100 60
Output:
Error: Invalid argument values.
valgrind --leak-check=full ./philo 5 2000 100 60
Output:
==12345== Memcheck, a memory error detector
==12345== All heap blocks were freed -- no leaks are possible
...
The Philosophers project serves as an in-depth exploration of multithreaded programming and synchronization in C. By simulating the Dining Philosophers problem, it provides practical experience in managing concurrent processes, utilizing mutexes for resource protection, and ensuring efficient memory management. This project not only reinforces theoretical concepts but also enhances problem-solving skills related to real-world programming challenges.