From 866fc8f181af2b4a7ba51a65b25ef06a0d15136c Mon Sep 17 00:00:00 2001 From: Diego Herrera Date: Thu, 7 Oct 2021 17:28:20 -0600 Subject: [PATCH 1/5] Initial implementation using Sys V semaphores --- .vscode/launch.json | 45 ++++++++ .vscode/settings.json | 52 +++++++++ code/kill-ipcs.sh | 22 ++++ code/makefile | 1 - code/src/constants.h | 21 ++++ code/src/main.cpp | 8 +- code/src/waiting-state/fork.cpp | 14 --- code/src/waiting-state/fork.h | 26 ----- code/src/waiting-state/philosopher.cpp | 142 ++++++++++++++++++++++++- code/src/waiting-state/philosopher.h | 13 ++- code/unittest/test-waiting-state.cpp | 79 +++++++++++++- 11 files changed, 369 insertions(+), 54 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100755 code/kill-ipcs.sh create mode 100644 code/src/constants.h delete mode 100644 code/src/waiting-state/fork.cpp delete mode 100644 code/src/waiting-state/fork.h diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..516d663 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Attach", + "type": "cppdbg", + "request": "attach", + "program": "${workspaceFolder}/code/bin/unittest", + "processId": "${command:pickProcess}", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/code/bin/unittest", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing -gdb-set follow-fork-mode child", + "ignoreFailures": true + }, + { + "text": "-gdb-set follow-fork-mode child" + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..440fd4a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,52 @@ +{ + "files.associations": { + "*.tcc": "cpp", + "limits": "cpp", + "type_traits": "cpp", + "iostream": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/code/kill-ipcs.sh b/code/kill-ipcs.sh new file mode 100755 index 0000000..f0146f7 --- /dev/null +++ b/code/kill-ipcs.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +ME=`whoami` + +IPCS_S=`ipcs -s | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "` +IPCS_M=`ipcs -m | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "` +IPCS_Q=`ipcs -q | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "` + + +for id in $IPCS_M; do + ipcrm -m $id; +done + +for id in $IPCS_S; do + ipcrm -s $id; +done + +for id in $IPCS_Q; do + ipcrm -q $id; +done + +ipcs \ No newline at end of file diff --git a/code/makefile b/code/makefile index a64da3d..4d31db8 100644 --- a/code/makefile +++ b/code/makefile @@ -58,7 +58,6 @@ $(OUTFILE): $(OBJFILES) $(CXX) -o $(BINDIR)/$@ $^ $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $(TESTFILE): $(TESTOBJFILES) - echo $(TESTOBJFILES) mkdir -p $(BINDIR) $(CXX) -o $(BINDIR)/$@ $^ $(CXXFLAGS) $(LDFLAGS) $(TSTLIBS) diff --git a/code/src/constants.h b/code/src/constants.h new file mode 100644 index 0000000..3b56c62 --- /dev/null +++ b/code/src/constants.h @@ -0,0 +1,21 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +// #ifdef __cplusplus +// extern "C" { +// #endif +#include + +namespace WaitingPhilosopher +{ + #define SEMKEYPATH "/tmp/dinPh" /* Path used on ftok for semget key */ + #define SHMKEYPATH SEMKEYPATH /* Path used on ftok for shmget key */ + #define OUTPUTPATH "/tmp/" /* Path used on ftok for semget key */ + + #define NUMSEMS 1 + #define SIZEOFSHMSEG 2048 +} + +#endif /* PHILOSOPHER_H_ */ + +// EOF \ No newline at end of file diff --git a/code/src/main.cpp b/code/src/main.cpp index 3551fbb..04d0151 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -1,6 +1,12 @@ #include "waiting-state/philosopher.h" +#include +#include +#include -int main() + +using namespace std; + +int main(int argc, char *argv[]) { return 0; } \ No newline at end of file diff --git a/code/src/waiting-state/fork.cpp b/code/src/waiting-state/fork.cpp deleted file mode 100644 index f725c60..0000000 --- a/code/src/waiting-state/fork.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "fork.h" - -using namespace WaitingPhilosopher; - -Fork::Fork() -{ - -} - -bool Fork::isBeingUsed() -{ - return IsUsed; -} - diff --git a/code/src/waiting-state/fork.h b/code/src/waiting-state/fork.h deleted file mode 100644 index d49f296..0000000 --- a/code/src/waiting-state/fork.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FORK_H_ -#define FORK_H_ - -// #ifdef __cplusplus -// extern "C" { -// #endif -#include - -namespace WaitingPhilosopher -{ - class Fork - { - public: - Fork(); - bool isBeingUsed(); - protected: - bool IsUsed = true; - - - - }; -} - -#endif /* FORK_H_ */ - -// EOF \ No newline at end of file diff --git a/code/src/waiting-state/philosopher.cpp b/code/src/waiting-state/philosopher.cpp index 3ac89c8..03d7e02 100644 --- a/code/src/waiting-state/philosopher.cpp +++ b/code/src/waiting-state/philosopher.cpp @@ -1,22 +1,156 @@ #include "philosopher.h" +#include "constants.h" + +#include +#include +#include + +#include + +#include using namespace WaitingPhilosopher; -Philosopher::Philosopher() +Philosopher::Philosopher(int index, int numPhilosophers) { + int rc= 0; + m_index = index; + m_numPhilosophers = numPhilosophers; + + /* Generate an IPC key for the semaphore set and the shared */ + /* memory segment. Typically, an application specific path and */ + /* id would be used to generate the IPC key. */ + m_semkey = ftok(SEMKEYPATH,m_index); + if ( m_semkey == (key_t)-1 ) + { + std::string error = "ID: " + std::to_string(m_index) + " ftok() for sem failed\n"; + perror(error.c_str()); + abort(); + } + + + /* Create a semaphore set using the IPC key. The number of */ + /* semaphores in the set is two. If a semaphore set already */ + /* exists for the key, return an error. The specified permissions*/ + /* give everyone read/write access to the semaphore set. */ + + m_semid = semget( m_semkey, NUMSEMS, 0666 | IPC_CREAT | IPC_EXCL ); + if ( m_semid == -1 ) + { + std::string error = "ID: " + std::to_string(m_index) + " semget() failed\n"; + perror(error.c_str()); + abort(); + } + + /* Initialize the first semaphore in the set to 0 and the */ + /* second semaphore in the set to 0. */ + /* */ + /* The first semaphore in the sem set means: */ + /* '1' -- The shared memory segment is being used. */ + /* '0' -- The shared memory segment is freed. */ + /* The '1' on this command is a no-op, because the SETALL command*/ + /* is used. */ + rc = semctl( m_semid, 0, SETVAL, 0); + if(rc == -1) + { + std::string error = "ID: " + std::to_string(m_index) + " semctl() initialization failed\n"; + perror(error.c_str()); + + } + + + +} + +Philosopher::~Philosopher() +{ + // int rc = semctl( m_semid, 1, IPC_RMID ); + // if (rc==-1) + // { + // std::cerr <<"ID: "< + +#include +#include + +#include +#include +#include + #include "waiting-state/philosopher.h" -#include "waiting-state/fork.h" +#include "constants.h" using namespace WaitingPhilosopher; using namespace std; +void deleteSemaphore(int id) +{ + key_t semkey = ftok(SEMKEYPATH,id); + if ( semkey == (key_t)-1 ) + { + std::cerr << "ID: "< 0) + { + pid = wait(&status); + printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status); + --n; // TODO(pts): Remove pid from the pids array. + } + + for (int i = 0; i < numPh; i++) + { + deleteSemaphore(i); + } + } From 63d981c4641a968bc8299322f9ac027d8164e1bf Mon Sep 17 00:00:00 2001 From: Diego Herrera Date: Thu, 7 Oct 2021 17:30:23 -0600 Subject: [PATCH 2/5] Changed fork for chopstick to avoid confusion --- README.md | 4 ++-- docs/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 262ed59..3e44373 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Implementation on Dining Philosophers problem on C++ ## Problem Statement -A certain number of philosophers spend their lives alternating between thinking and eating. They are seated around a circular table. There is a fork placed between each pair of neighboring philosophers. Each philosopher has access to the forks at her left and right. In order to eat, a philosopher must be in possession of both forks. A philosopher may only pick up one fork at a time. Each philosopher attempts to pick up the left fork first and then the right fork. When done eating, a philosopher puts both forks back down on the table and begins thinking. Since the philosophers are sharing forks, it is not possible for all of them to be eating at the same time. +A certain number of philosophers spend their lives alternating between thinking and eating. They are seated around a circular table. There is a chopstick placed between each pair of neighboring philosophers. Each philosopher has access to the chopsticks at her left and right. In order to eat, a philosopher must be in possession of both chopsticks. A philosopher may only pick up one chopstick at a time. Each philosopher attempts to pick up the left chopstick first and then the right chopstick. When done eating, a philosopher puts both chopsticks back down on the table and begins thinking. Since the philosophers are sharing chopsticks, it is not possible for all of them to be eating at the same time. This was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise. @@ -15,7 +15,7 @@ This was originally formulated in 1965 by Edsger Dijkstra as a student exam exer ### Waiting State - The philosopher enters into a waiting state when neighbors are eating - - When its neighbors are done, go for the forks + - When its neighbors are done, go for the chopsticks - Its neighbors can't enter into the waiting state if there is a neighbor already waiting ## Tests diff --git a/docs/index.md b/docs/index.md index 460c766..01e8e48 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,6 +5,6 @@ ## Problem Statement -A certain number of philosophers spend their lives alternating between thinking and eating. They are seated around a circular table. There is a fork placed between each pair of neighboring philosophers. Each philosopher has access to the forks at her left and right. In order to eat, a philosopher must be in possession of both forks. A philosopher may only pick up one fork at a time. Each philosopher attempts to pick up the left fork first and then the right fork. When done eating, a philosopher puts both forks back down on the table and begins thinking. Since the philosophers are sharing forks, it is not possible for all of them to be eating at the same time. +A certain number of philosophers spend their lives alternating between thinking and eating. They are seated around a circular table. There is a chopstick placed between each pair of neighboring philosophers. Each philosopher has access to the chopsticks at her left and right. In order to eat, a philosopher must be in possession of both chopsticks. A philosopher may only pick up one chopstick at a time. Each philosopher attempts to pick up the left chopstick first and then the right chopstick. When done eating, a philosopher puts both chopsticks back down on the table and begins thinking. Since the philosophers are sharing chopsticks, it is not possible for all of them to be eating at the same time. This was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise. From e36ee5aaeb525e89fa6e5d7d042ecb294bed13a1 Mon Sep 17 00:00:00 2001 From: Diego Herrera Date: Thu, 7 Oct 2021 18:51:29 -0600 Subject: [PATCH 3/5] Partially working solution --- code/src/waiting-state/chopstick.cpp | 62 ++++++++++++ code/src/waiting-state/chopstick.h | 25 +++++ code/src/waiting-state/philosopher.cpp | 131 ++++++++++--------------- code/src/waiting-state/philosopher.h | 7 +- code/unittest/test-waiting-state.cpp | 14 +-- 5 files changed, 148 insertions(+), 91 deletions(-) create mode 100644 code/src/waiting-state/chopstick.cpp create mode 100644 code/src/waiting-state/chopstick.h diff --git a/code/src/waiting-state/chopstick.cpp b/code/src/waiting-state/chopstick.cpp new file mode 100644 index 0000000..47d15df --- /dev/null +++ b/code/src/waiting-state/chopstick.cpp @@ -0,0 +1,62 @@ +#include "chopstick.h" +#include "constants.h" + +#include +#include +#include + +#include + +#include + +using namespace WaitingPhilosopher; + +Chopstick::Chopstick(int index) +{ + int rc= 0; + m_index = index; + + /* Generate an IPC key for the semaphore set and the shared */ + /* memory segment. Typically, an application specific path and */ + /* id would be used to generate the IPC key. */ + m_semkey = ftok(SEMKEYPATH,m_index); + if ( m_semkey == (key_t)-1 ) + { + std::string error = "ID: " + std::to_string(m_index) + " ftok() for sem failed\n"; + perror(error.c_str()); + abort(); + } + + + /* Create a semaphore set using the IPC key. The number of */ + /* semaphores in the set is two. If a semaphore set already */ + /* exists for the key, return an error. The specified permissions*/ + /* give everyone read/write access to the semaphore set. */ + + m_semid = semget( m_semkey, NUMSEMS, 0666 | IPC_CREAT | IPC_EXCL ); + if ( m_semid == -1 ) + { + std::string error = "ID: " + std::to_string(m_index) + " semget() failed\n"; + perror(error.c_str()); + abort(); + } + + // Initialize the semaphore in the set to 0 + rc = semctl( m_semid, 0, SETVAL, 0); + if(rc == -1) + { + std::string error = "ID: " + std::to_string(m_index) + " semctl() initialization failed\n"; + perror(error.c_str()); + + } +} + +void Chopstick::putAway() +{ + int rc = semctl( m_semid, 1, IPC_RMID ); + if (rc==-1) + { + std::string error = "ID: " + std::to_string(m_index) + " semctl() remove id failed\n"; + perror(error.c_str()); + } +} diff --git a/code/src/waiting-state/chopstick.h b/code/src/waiting-state/chopstick.h new file mode 100644 index 0000000..ecf45e4 --- /dev/null +++ b/code/src/waiting-state/chopstick.h @@ -0,0 +1,25 @@ +#ifndef CHOPSTICK_H_ +#define CHOPSTICK_H_ + +// #ifdef __cplusplus +// extern "C" { +// #endif +#include + +namespace WaitingPhilosopher +{ + class Chopstick + { + public: + Chopstick(int index); + void putAway(); + protected: + int m_index; + int m_semid; + key_t m_semkey; + }; +} + +#endif /* CHOPSTICK_H_ */ + +// EOF \ No newline at end of file diff --git a/code/src/waiting-state/philosopher.cpp b/code/src/waiting-state/philosopher.cpp index 03d7e02..09aae4e 100644 --- a/code/src/waiting-state/philosopher.cpp +++ b/code/src/waiting-state/philosopher.cpp @@ -13,113 +13,81 @@ using namespace WaitingPhilosopher; Philosopher::Philosopher(int index, int numPhilosophers) { - int rc= 0; - m_index = index; - m_numPhilosophers = numPhilosophers; - - /* Generate an IPC key for the semaphore set and the shared */ - /* memory segment. Typically, an application specific path and */ - /* id would be used to generate the IPC key. */ - m_semkey = ftok(SEMKEYPATH,m_index); - if ( m_semkey == (key_t)-1 ) - { - std::string error = "ID: " + std::to_string(m_index) + " ftok() for sem failed\n"; - perror(error.c_str()); - abort(); - } - - - /* Create a semaphore set using the IPC key. The number of */ - /* semaphores in the set is two. If a semaphore set already */ - /* exists for the key, return an error. The specified permissions*/ - /* give everyone read/write access to the semaphore set. */ - - m_semid = semget( m_semkey, NUMSEMS, 0666 | IPC_CREAT | IPC_EXCL ); - if ( m_semid == -1 ) - { - std::string error = "ID: " + std::to_string(m_index) + " semget() failed\n"; - perror(error.c_str()); - abort(); - } - - /* Initialize the first semaphore in the set to 0 and the */ - /* second semaphore in the set to 0. */ - /* */ - /* The first semaphore in the sem set means: */ - /* '1' -- The shared memory segment is being used. */ - /* '0' -- The shared memory segment is freed. */ - - /* The '1' on this command is a no-op, because the SETALL command*/ - /* is used. */ - rc = semctl( m_semid, 0, SETVAL, 0); - if(rc == -1) - { - std::string error = "ID: " + std::to_string(m_index) + " semctl() initialization failed\n"; - perror(error.c_str()); - - } - - - + m_index = index; + m_numPhilosophers = numPhilosophers; } -Philosopher::~Philosopher() -{ - // int rc = semctl( m_semid, 1, IPC_RMID ); - // if (rc==-1) - // { - // std::cerr <<"ID: "< #include "waiting-state/philosopher.h" +#include "waiting-state/chopstick.h" #include "constants.h" using namespace WaitingPhilosopher; @@ -66,14 +67,16 @@ class WaitingPhilosopherTest : public testing::Test TEST_F(WaitingPhilosopherTest, evenPhilosophers) { - int numPh = 3; + int numPh = 5; Philosopher* philosophers = (Philosopher*)malloc(sizeof(Philosopher) * numPh); + Chopstick* chopsticks = (Chopstick*)malloc(sizeof(Chopstick) * numPh);; pid_t pids[numPh]; for (int i = 0; i < numPh; i++) { - philosophers[i] = Philosopher(i, numPh); + philosophers[i] = Philosopher(i, numPh); + chopsticks[i] = Chopstick(i); } @@ -86,7 +89,7 @@ TEST_F(WaitingPhilosopherTest, evenPhilosophers) } else if (pids[i] == 0) { - philosophers[i].eat(); + philosophers[i].dine(); exit(0); } } @@ -103,10 +106,7 @@ TEST_F(WaitingPhilosopherTest, evenPhilosophers) for (int i = 0; i < numPh; i++) { - deleteSemaphore(i); + chopsticks[i].putAway(); } - - - } From 70efd1b3fab09da6cd383ec617c4d781ca73a461 Mon Sep 17 00:00:00 2001 From: Diego Herrera Date: Thu, 7 Oct 2021 21:38:45 -0600 Subject: [PATCH 4/5] Added dining table structre and added new tests --- .vscode/launch.json | 23 +++- code/src/main.cpp | 97 ++++++++++++++++- code/src/waiting-state/chopstick.cpp | 2 +- code/src/waiting-state/diningTable.cpp | 63 +++++++++++ code/src/waiting-state/diningTable.h | 20 ++++ code/src/waiting-state/philosopher.cpp | 6 +- code/unittest/test-waiting-state.cpp | 143 +++++++++++++++---------- 7 files changed, 284 insertions(+), 70 deletions(-) create mode 100644 code/src/waiting-state/diningTable.cpp create mode 100644 code/src/waiting-state/diningTable.h diff --git a/.vscode/launch.json b/.vscode/launch.json index 516d663..7ca4ac2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,11 +4,30 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "(gdb) Unittest Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/code/bin/unittest", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, { "name": "(gdb) Attach", "type": "cppdbg", "request": "attach", - "program": "${workspaceFolder}/code/bin/unittest", + "program": "${workspaceFolder}/code/bin/dining-philosophers", "processId": "${command:pickProcess}", "MIMode": "gdb", "setupCommands": [ @@ -23,7 +42,7 @@ "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/code/bin/unittest", + "program": "${workspaceFolder}/code/bin/dining-philosophers", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/code/src/main.cpp b/code/src/main.cpp index 04d0151..771ffbf 100644 --- a/code/src/main.cpp +++ b/code/src/main.cpp @@ -1,12 +1,99 @@ -#include "waiting-state/philosopher.h" -#include -#include +#include "waiting-state/diningTable.h" + #include +#include +#include +#include +#include /* read, write, pipe, _exit */ +#include using namespace std; -int main(int argc, char *argv[]) +/* Flag set by ‘--verbose’. */ +static int verbose_flag; + + + +void displayUsage() +{ + cout << + "-n/--number : Number 'n' of philosophers. \n" + "-h/--help: Show help\n"; + exit(EXIT_SUCCESS); +} + +int main (int argc, char **argv) { - return 0; + int c; + int n = 5; + + while (true) + { + static struct option long_options[] = + { + /* These options set a flag. */ + {"verbose", no_argument, &verbose_flag, 1}, + {"brief", no_argument, &verbose_flag, 0}, + /* These options don’t set a flag. + We distinguish them by their indices. */ + + {"number", required_argument, 0, 'n'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, "hn:", + long_options, &option_index); + + + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case 'n': + n = atoi(optarg); + break; + case 'h': + case '?': + default: + displayUsage(); + abort (); + } + } + + /* Instead of reporting ‘--verbose’ + and ‘--brief’ as they are encountered, + we report the final status resulting from them. */ + if (verbose_flag) + puts ("verbose flag is set"); + + /* Print any remaining command line arguments (not options). */ + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + putchar ('\n'); + } + + WaitingPhilosopher::DiningTable::startDinner(n); + + exit (EXIT_SUCCESS); } \ No newline at end of file diff --git a/code/src/waiting-state/chopstick.cpp b/code/src/waiting-state/chopstick.cpp index 47d15df..6d1a7f5 100644 --- a/code/src/waiting-state/chopstick.cpp +++ b/code/src/waiting-state/chopstick.cpp @@ -53,7 +53,7 @@ Chopstick::Chopstick(int index) void Chopstick::putAway() { - int rc = semctl( m_semid, 1, IPC_RMID ); + int rc = semctl( m_semid, 0, IPC_RMID ); if (rc==-1) { std::string error = "ID: " + std::to_string(m_index) + " semctl() remove id failed\n"; diff --git a/code/src/waiting-state/diningTable.cpp b/code/src/waiting-state/diningTable.cpp new file mode 100644 index 0000000..88201b8 --- /dev/null +++ b/code/src/waiting-state/diningTable.cpp @@ -0,0 +1,63 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include "diningTable.h" +#include "philosopher.h" +#include "chopstick.h" +#include "constants.h" + +using namespace WaitingPhilosopher; +using namespace std; + +void DiningTable::startDinner(int numberPhilosophers) +{ + Philosopher* philosophers = (Philosopher*)malloc(sizeof(Philosopher) * numberPhilosophers); + Chopstick* chopsticks = (Chopstick*)malloc(sizeof(Chopstick) * numberPhilosophers);; + pid_t pids[numberPhilosophers]; + + printf("\n------ Dining Philosophers ------\n\n\n"); + printf("%i philosophers dining\n\n", numberPhilosophers); + for (int i = 0; i < numberPhilosophers; i++) + { + philosophers[i] = Philosopher(i, numberPhilosophers); + chopsticks[i] = Chopstick(i); + } + + + for (int i = 0; i < numberPhilosophers; i++) + { + if ((pids[i] = fork()) < 0) + { + perror("fork"); + abort(); + } + else if (pids[i] == 0) + { + philosophers[i].dine(); + exit(0); + } + } + + int status; + pid_t pid; + int n = numberPhilosophers; + while (n > 0) + { + pid = wait(&status); + //printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status); + --n; // TODO(pts): Remove pid from the pids array. + } + + for (int i = 0; i < numberPhilosophers; i++) + { + chopsticks[i].putAway(); + } + + printf("\nFinished Diner\n"); +} \ No newline at end of file diff --git a/code/src/waiting-state/diningTable.h b/code/src/waiting-state/diningTable.h new file mode 100644 index 0000000..2f3c864 --- /dev/null +++ b/code/src/waiting-state/diningTable.h @@ -0,0 +1,20 @@ +#ifndef DININGTABLE_H_ +#define DININGTABLE_H_ + +// #ifdef __cplusplus +// extern "C" { +// #endif +#include + +namespace WaitingPhilosopher +{ + class DiningTable + { + public: + static void startDinner(int numberPhilosophers); + }; +} + +#endif /* DININGTABLE_H_ */ + +// EOF \ No newline at end of file diff --git a/code/src/waiting-state/philosopher.cpp b/code/src/waiting-state/philosopher.cpp index 09aae4e..c2a5ef5 100644 --- a/code/src/waiting-state/philosopher.cpp +++ b/code/src/waiting-state/philosopher.cpp @@ -65,7 +65,7 @@ void Philosopher::waitChopstick(int index) void Philosopher::pickupChopstick(int index) { - printf("ID: %i - pickup chopstick: %i\n",m_index,index); + printf("ID: %i - Pickup chopstick: %i\n",m_index,index); // std::cout<<"Me: "< 0) - { - pid = wait(&status); - printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status); - --n; // TODO(pts): Remove pid from the pids array. - } + aristotle.pickupChopstick(id); - for (int i = 0; i < numPh; i++) - { - chopsticks[i].putAway(); - } + semval = semctl( semId, 0, GETVAL , arg ); + ASSERT_EQ ( semval, 1 ); + + aristotle.pickupChopstick(id); + + semval = semctl( semId, 0, GETVAL , arg ); + ASSERT_EQ ( semval, 2 ); + + aristotle.putdownChopstick(id); + + semval = semctl( semId, 0, GETVAL , arg ); + ASSERT_EQ ( semval, 1 ); + + + testChopstick.putAway(); + + semKey = ftok(SEMKEYPATH,id); + ASSERT_FALSE( semKey == (key_t)-1 ); + + semId = semget( semKey, NUMSEMS, 0666); + ASSERT_TRUE ( semId == -1 ); +} + + +TEST_F(WaitingPhilosopherTest, DISABLED_evenPhilosophers) +{ + DiningTable::startDinner(6); +} + +TEST_F(WaitingPhilosopherTest, DISABLED_oddPhilosophers) +{ + DiningTable::startDinner(5); } From ea560b7031756aad711d7c64c84d2fe449f0935f Mon Sep 17 00:00:00 2001 From: Diego Herrera Date: Thu, 7 Oct 2021 22:06:07 -0600 Subject: [PATCH 5/5] Updated path of semaphores --- code/src/constants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/src/constants.h b/code/src/constants.h index 3b56c62..48ea946 100644 --- a/code/src/constants.h +++ b/code/src/constants.h @@ -8,9 +8,9 @@ namespace WaitingPhilosopher { - #define SEMKEYPATH "/tmp/dinPh" /* Path used on ftok for semget key */ + #define SEMKEYPATH "/tmp" /* Path used on ftok for semget key */ #define SHMKEYPATH SEMKEYPATH /* Path used on ftok for shmget key */ - #define OUTPUTPATH "/tmp/" /* Path used on ftok for semget key */ + #define OUTPUTPATH "/tmp" /* Path used on ftok for semget key */ #define NUMSEMS 1 #define SIZEOFSHMSEG 2048