Skip to content

Commit

Permalink
Merge pull request #10 from herrera-diego/herrera-diego/waiting-state
Browse files Browse the repository at this point in the history
Herrera diego/waiting state
  • Loading branch information
herrera-diego authored Oct 8, 2021
2 parents 2693887 + ea560b7 commit 08ea58d
Show file tree
Hide file tree
Showing 17 changed files with 648 additions and 62 deletions.
64 changes: 64 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
// 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) 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/dining-philosophers",
"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/dining-philosophers",
"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"
}
]
}
]
}
52 changes: 52 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ 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.

## Solution

### 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
Expand Down
22 changes: 22 additions & 0 deletions code/kill-ipcs.sh
Original file line number Diff line number Diff line change
@@ -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
1 change: 0 additions & 1 deletion code/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
21 changes: 21 additions & 0 deletions code/src/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H

// #ifdef __cplusplus
// extern "C" {
// #endif
#include <string>

namespace WaitingPhilosopher
{
#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 NUMSEMS 1
#define SIZEOFSHMSEG 2048
}

#endif /* PHILOSOPHER_H_ */

// EOF
99 changes: 96 additions & 3 deletions code/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,99 @@
#include "waiting-state/philosopher.h"
#include "waiting-state/diningTable.h"

int main()
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <iostream>
#include <unistd.h> /* read, write, pipe, _exit */
#include <string.h>


using namespace std;

/* Flag set by ‘--verbose’. */
static int verbose_flag;



void displayUsage()
{
cout <<
"-n/--number <n>: Number 'n' of philosophers. <Default: 5>\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);
}
62 changes: 62 additions & 0 deletions code/src/waiting-state/chopstick.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "chopstick.h"
#include "constants.h"

#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#include <iostream>

#include <unistd.h>

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, 0, IPC_RMID );
if (rc==-1)
{
std::string error = "ID: " + std::to_string(m_index) + " semctl() remove id failed\n";
perror(error.c_str());
}
}
25 changes: 25 additions & 0 deletions code/src/waiting-state/chopstick.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef CHOPSTICK_H_
#define CHOPSTICK_H_

// #ifdef __cplusplus
// extern "C" {
// #endif
#include <string>

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
Loading

0 comments on commit 08ea58d

Please sign in to comment.