mirror of
https://github.com/Hizenberg469/Dining_philosopher.git
synced 2026-04-19 18:02:25 +03:00
Dining Philosopher Problem Implemented using pthread POSIX Library
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*vsidx
|
||||
*.opendb
|
||||
.vs
|
||||
out
|
||||
21
CMakeLists.txt
Normal file
21
CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
# CMakeList.txt : CMake project for DiningPhilosopher, include source and define
|
||||
# project specific logic here.
|
||||
#
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
# Enable Hot Reload for MSVC compilers if supported.
|
||||
if (POLICY CMP0141)
|
||||
cmake_policy(SET CMP0141 NEW)
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
|
||||
endif()
|
||||
|
||||
project ("DiningPhilosopher")
|
||||
|
||||
# Add source to this project's executable.
|
||||
add_executable (DiningPhilosopher "DiningPhilosopher.c" "din_ph.h")
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
set_property(TARGET DiningPhilosopher PROPERTY CXX_STANDARD 20)
|
||||
endif()
|
||||
|
||||
# TODO: Add tests and install targets if needed.
|
||||
101
CMakePresets.json
Normal file
101
CMakePresets.json
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "windows-base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "cl.exe",
|
||||
"CMAKE_CXX_COMPILER": "cl.exe"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-debug",
|
||||
"displayName": "x64 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-release",
|
||||
"displayName": "x64 Release",
|
||||
"inherits": "x64-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-debug",
|
||||
"displayName": "x86 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x86",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-release",
|
||||
"displayName": "x86 Release",
|
||||
"inherits": "x86-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug",
|
||||
"displayName": "Linux Debug",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-debug",
|
||||
"displayName": "macOS Debug",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
241
DiningPhilosopher.c
Normal file
241
DiningPhilosopher.c
Normal file
@@ -0,0 +1,241 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "din_ph.h"
|
||||
|
||||
|
||||
#define N_PHILOSOPHER 5
|
||||
|
||||
static phil_t phil[N_PHILOSOPHER];
|
||||
static spoon_t spoon[N_PHILOSOPHER];
|
||||
|
||||
static spoon_t* phil_get_right_spoon(phil_t* phil) {
|
||||
|
||||
int phil_id = phil->phil_id;
|
||||
|
||||
if (phil_id == 0) {
|
||||
return &spoon[N_PHILOSOPHER-1];
|
||||
}
|
||||
|
||||
return &spoon[phil_id - 1];
|
||||
}
|
||||
|
||||
static spoon_t* phil_get_left_spoon(phil_t* phil) {
|
||||
|
||||
int phil_id = phil->phil_id;
|
||||
return &spoon[phil_id];
|
||||
}
|
||||
|
||||
void
|
||||
phil_eat(phil_t* phil) {
|
||||
|
||||
spoon_t* left_spoon = phil_get_left_spoon(phil);
|
||||
spoon_t* right_spoon = phil_get_right_spoon(phil);
|
||||
|
||||
/*
|
||||
Check condition that Phil is eating with right set of spoons
|
||||
*/
|
||||
|
||||
assert(left_spoon->phil == phil);
|
||||
assert(right_spoon->phil == phil);
|
||||
assert(left_spoon->is_used == true);
|
||||
assert(right_spoon->is_used == true);
|
||||
|
||||
phil->eat_count++;
|
||||
|
||||
printf("Phil %d eats with spoon [%d , %d] for %d times\n",
|
||||
phil->phil_id, left_spoon->spoon_id, right_spoon->spoon_id,
|
||||
phil->eat_count);
|
||||
sleep(1); /* let the philosopher eat the cake for 1 second. */
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
philosopher_release_both_spoons(phil_t* phil) {
|
||||
|
||||
spoon_t* left_spoon = phil_get_left_spoon(phil);
|
||||
spoon_t* right_spoon = phil_get_right_spoon(phil);
|
||||
|
||||
/* . . . */
|
||||
|
||||
pthread_mutex_lock(&left_spoon->mutex);
|
||||
pthread_mutex_lock(&right_spoon->mutex);
|
||||
|
||||
assert(left_spoon->phil == phil);
|
||||
assert(left_spoon->is_used == true);
|
||||
|
||||
assert(right_spoon->phil == phil);
|
||||
assert(right_spoon->is_used == true);
|
||||
|
||||
printf("phil %d releasing the left spoon %d\n", phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
left_spoon->phil = NULL;
|
||||
left_spoon->is_used = false;
|
||||
|
||||
pthread_cond_signal(&left_spoon->cv);
|
||||
printf("phil %d signalled the phil waiting for left spoon %d\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
pthread_mutex_unlock(&left_spoon->mutex);
|
||||
|
||||
printf("phil %d releasing the right spoon %d\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
|
||||
right_spoon->phil = NULL;
|
||||
right_spoon->is_used = false;
|
||||
pthread_cond_signal(&right_spoon->cv);
|
||||
|
||||
printf("phil %d signalled the phil waiting for right spoon %d\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
|
||||
pthread_mutex_unlock(&right_spoon->mutex);
|
||||
}
|
||||
|
||||
bool
|
||||
philosopher_access_both_spoons(phil_t* phil) {
|
||||
|
||||
spoon_t* left_spoon = phil_get_left_spoon(phil);
|
||||
spoon_t* right_spoon = phil_get_right_spoon(phil);
|
||||
|
||||
/* before checking status of the spoon, lock it, While one
|
||||
philosopher is inspecting the state of the spoon, no
|
||||
other phil must change it */
|
||||
|
||||
printf("Phil %d waiting for lock on left spoon %d\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
pthread_mutex_lock(&left_spoon->mutex);
|
||||
printf("Phil %d inspecting left spoon %d state\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
/* Case 1 : if spoon is begin used by some other phil, then wait */
|
||||
while (left_spoon->is_used &&
|
||||
left_spoon->phil != phil) {
|
||||
|
||||
printf("phil %d blocks as left spoon %d is not available\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
pthread_cond_wait(&left_spoon->cv, &left_spoon->mutex);
|
||||
|
||||
printf("phil %d recvs signal to grab spoon %d\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
}
|
||||
|
||||
|
||||
/* Case 2 : if spoon is available, grab it and try for another spoon */
|
||||
|
||||
printf("phil %d finds left spoon %d available, trying to grab it\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
left_spoon->is_used = true;
|
||||
left_spoon->phil = phil;
|
||||
printf("phil %d has successfully grabbed the left spoon %d\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
pthread_mutex_unlock(&left_spoon->mutex);
|
||||
|
||||
/* Case 2.1 : Trying to grab the right spoon now */
|
||||
printf("phil %d now making an attempt to grab the right spoon %d\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
|
||||
/* lock the right spoon before inspecting its state */
|
||||
printf("phil %d waiting for lock on right spoon %d\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
|
||||
pthread_mutex_lock(&right_spoon->mutex);
|
||||
|
||||
printf("phil %d inspecting right spoon %d state\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
|
||||
if (right_spoon->is_used == false) {
|
||||
/* right spoon is also available, grab it and eat */
|
||||
right_spoon->is_used = true;
|
||||
right_spoon->phil = phil;
|
||||
pthread_mutex_unlock(&right_spoon->mutex);
|
||||
return true;
|
||||
}
|
||||
else if (right_spoon->is_used == true) {
|
||||
|
||||
if (right_spoon->phil != phil) {
|
||||
printf("phil %d finds right spoon %d is already used by phil %d"
|
||||
" realeasing the left spoon as well\n",
|
||||
phil->phil_id, right_spoon->spoon_id, right_spoon->phil->phil_id);
|
||||
|
||||
pthread_mutex_lock(&left_spoon->mutex);
|
||||
assert(left_spoon->is_used == true);
|
||||
|
||||
assert(left_spoon->is_used == true);
|
||||
|
||||
left_spoon->is_used = false;
|
||||
left_spoon->phil = NULL;
|
||||
|
||||
printf("phil %d release the left spoon %d\n",
|
||||
phil->phil_id, left_spoon->spoon_id);
|
||||
|
||||
pthread_mutex_unlock(&left_spoon->mutex);
|
||||
pthread_mutex_unlock(&right_spoon->mutex);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
printf("phil %d already has right spoon %d in hand\n",
|
||||
phil->phil_id, right_spoon->spoon_id);
|
||||
pthread_mutex_unlock(&right_spoon->mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
assert(0); /* should be dead code */
|
||||
return false;
|
||||
}
|
||||
|
||||
void*
|
||||
philosopher_fn(void* arg) {
|
||||
|
||||
/* Start implementation of core logic from here */
|
||||
|
||||
phil_t* phil = (phil_t*)arg;
|
||||
|
||||
while (1) {
|
||||
|
||||
if (philosopher_access_both_spoons(phil)) {
|
||||
|
||||
phil_eat(phil);
|
||||
philosopher_release_both_spoons(phil);
|
||||
sleep(1); /* Phil wait for 1 sec to again attempt to get the spoon */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main(int argv, char* argc[]) {
|
||||
|
||||
int i = 0;
|
||||
pthread_attr_t attr;
|
||||
|
||||
/*Initialize all spoons*/
|
||||
for (i = 0; i < N_PHILOSOPHER; i++) {
|
||||
|
||||
spoon[i].spoon_id = i;
|
||||
spoon[i].is_used = false;
|
||||
spoon[i].phil = NULL;
|
||||
pthread_mutex_init(&spoon[i].mutex, NULL);
|
||||
pthread_cond_init(&spoon[i].cv, NULL);
|
||||
|
||||
}
|
||||
|
||||
/* Default attributes of all Philosopher threads */
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
/* create philosopher threads */
|
||||
for (i = 0; i < N_PHILOSOPHER; i++) {
|
||||
|
||||
phil[i].phil_id = i;
|
||||
phil[i].eat_count = 0;
|
||||
pthread_create(&phil[i].thread_handle, &attr, philosopher_fn, &phil[i]);
|
||||
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
return 0;
|
||||
}
|
||||
23
din_ph.h
Normal file
23
din_ph.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef __DIN_PH_H__
|
||||
#define __DIN_PH_H__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct phil_ {
|
||||
|
||||
int phil_id;
|
||||
pthread_t thread_handle;
|
||||
int eat_count;
|
||||
} phil_t;
|
||||
|
||||
typedef struct spoon_ {
|
||||
|
||||
int spoon_id;
|
||||
bool is_used; /* bool to indicate if the spoon is being used or not */
|
||||
phil_t* phil; /* If used, then which philosopher is using it */
|
||||
pthread_mutex_t mutex; /* For Mutual Exclusion */
|
||||
pthread_cond_t cv; /* For thread Co-ordination competing for this Resource */
|
||||
} spoon_t;
|
||||
|
||||
#endif /* __DIN_PH_H__ */
|
||||
Reference in New Issue
Block a user