Adding first commit.
This commit is contained in:
commit
e234a48faf
7
Doxyfile
Normal file
7
Doxyfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
GENERATE_HTML=yes
|
||||||
|
EXTRACT_ALL=yes
|
||||||
|
RECURSIVE=yes
|
||||||
|
INPUT=../include
|
||||||
|
DISABLE_INDEX = YES
|
||||||
|
GENERATE_TREEVIEW = YES
|
||||||
|
PROJECT_NAME=dining-philosophers
|
7
include/philosopher-state.hpp
Normal file
7
include/philosopher-state.hpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
enum class PhilosopherState {
|
||||||
|
THINKING,
|
||||||
|
HUNGRY,
|
||||||
|
EATING,
|
||||||
|
};
|
||||||
|
|
63
include/philosopher.hpp
Normal file
63
include/philosopher.hpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <iostream>
|
||||||
|
#include <semaphore>
|
||||||
|
|
||||||
|
#include <random.hpp>
|
||||||
|
#include <philosopher-state.hpp>
|
||||||
|
|
||||||
|
class Philosopher;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Philosopher> PhilosopherPtr;
|
||||||
|
typedef std::vector<PhilosopherPtr> ListOfPhilosophers;
|
||||||
|
typedef std::shared_ptr<ListOfPhilosophers> ListOfPhilosophersPtr;
|
||||||
|
extern std::mutex changingForkState;
|
||||||
|
extern std::mutex printing;
|
||||||
|
|
||||||
|
class Philosopher {
|
||||||
|
private:
|
||||||
|
int numberOfPhilosopher;
|
||||||
|
|
||||||
|
PhilosopherState state{PhilosopherState::THINKING};
|
||||||
|
|
||||||
|
ListOfPhilosophersPtr philosophers;
|
||||||
|
|
||||||
|
void
|
||||||
|
setState(PhilosopherState state);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
leftPhilosopherNumber(void);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
rightPhilosopherNumber(void);
|
||||||
|
|
||||||
|
PhilosopherPtr
|
||||||
|
leftPhilosopher(void);
|
||||||
|
|
||||||
|
PhilosopherPtr
|
||||||
|
rightPhilosopher(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
think();
|
||||||
|
|
||||||
|
void
|
||||||
|
takeForks();
|
||||||
|
|
||||||
|
void
|
||||||
|
eat();
|
||||||
|
|
||||||
|
void
|
||||||
|
putForks();
|
||||||
|
|
||||||
|
public:
|
||||||
|
PhilosopherState
|
||||||
|
getState();
|
||||||
|
Philosopher(ListOfPhilosophersPtr philosophers, int numberOfPhilosopher);
|
||||||
|
std::binary_semaphore hasBothForks{0};
|
||||||
|
void startThread();
|
||||||
|
void test();
|
||||||
|
};
|
||||||
|
|
4
include/random.hpp
Normal file
4
include/random.hpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
size_t
|
||||||
|
random(size_t min, size_t max);
|
31
meson.build
Normal file
31
meson.build
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
project('tech.owlcode.dining-philosophers', 'cpp')
|
||||||
|
add_global_arguments('-std=c++20', '-D_DEFAULT_SOURCE', language : 'cpp')
|
||||||
|
|
||||||
|
inc = include_directories('include')
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
'src/main.cpp',
|
||||||
|
'src/random.cpp',
|
||||||
|
'src/philosopher.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
|
inc = [
|
||||||
|
'include'
|
||||||
|
]
|
||||||
|
|
||||||
|
link_arguments = [
|
||||||
|
]
|
||||||
|
|
||||||
|
executable('dining',
|
||||||
|
sources,
|
||||||
|
include_directories : inc,
|
||||||
|
install : true,
|
||||||
|
link_args : link_arguments,
|
||||||
|
)
|
||||||
|
doxygen = find_program('doxygen', required : false)
|
||||||
|
if doxygen.found()
|
||||||
|
message('Doxygen found')
|
||||||
|
run_target('docs', command : [doxygen, meson.source_root() + '/Doxyfile'])
|
||||||
|
else
|
||||||
|
warning('Documentation disabled without doxygen')
|
||||||
|
endif
|
46
src/main.cpp
Normal file
46
src/main.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <random>
|
||||||
|
#include <philosopher.hpp>
|
||||||
|
|
||||||
|
class Philosopher;
|
||||||
|
|
||||||
|
void
|
||||||
|
findNumberOfPhilosophersInParams(const int argc, char **argv, int *const numberOfPhilosophers);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv) {
|
||||||
|
ListOfPhilosophersPtr philosophers;
|
||||||
|
philosophers = ListOfPhilosophersPtr(new ListOfPhilosophers());
|
||||||
|
int numberOfPhilosophers = 5;
|
||||||
|
findNumberOfPhilosophersInParams(argc, argv, &numberOfPhilosophers);
|
||||||
|
printf("%d philosophers to create.\n", numberOfPhilosophers);
|
||||||
|
for (int i = 0; i < numberOfPhilosophers; i++) {
|
||||||
|
printf("Creating philosopher: %d.\n", i);
|
||||||
|
philosophers->push_back(PhilosopherPtr(new Philosopher(philosophers, i)));
|
||||||
|
}
|
||||||
|
std::vector<std::jthread> threads;
|
||||||
|
for (unsigned long int i = 0; i < philosophers->size(); i++) {
|
||||||
|
std::shared_ptr<unsigned long> numberOfPhilosopher(new unsigned long(i));
|
||||||
|
threads.push_back(std::jthread([philosophers, numberOfPhilosopher] {
|
||||||
|
(*philosophers)[*numberOfPhilosopher]->startThread();
|
||||||
|
} ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
findNumberOfPhilosophersInParams(const int argc, char **argv, int *const numberOfPhilosophers) {
|
||||||
|
if (argc >= 2) {
|
||||||
|
const char *numberOfPhilosophersAsString = argv[1];
|
||||||
|
try {
|
||||||
|
*numberOfPhilosophers = std::stoi(numberOfPhilosophersAsString, NULL, 10);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
printf("Unable to read the number of philosophers, continuing\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
99
src/philosopher.cpp
Normal file
99
src/philosopher.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include <philosopher.hpp>
|
||||||
|
|
||||||
|
std::mutex changingForkState;
|
||||||
|
std::mutex printing;
|
||||||
|
void
|
||||||
|
Philosopher::setState(PhilosopherState state) {
|
||||||
|
this->state = state;
|
||||||
|
}
|
||||||
|
size_t
|
||||||
|
Philosopher::leftPhilosopherNumber(void) {
|
||||||
|
return (numberOfPhilosopher - 1 + philosophers->size()) % philosophers->size();
|
||||||
|
}
|
||||||
|
size_t
|
||||||
|
Philosopher::rightPhilosopherNumber(void) {
|
||||||
|
return (numberOfPhilosopher + 1) % philosophers->size();
|
||||||
|
}
|
||||||
|
PhilosopherPtr
|
||||||
|
Philosopher::leftPhilosopher(void) {
|
||||||
|
return (*philosophers)[leftPhilosopherNumber()];
|
||||||
|
}
|
||||||
|
PhilosopherPtr
|
||||||
|
Philosopher::rightPhilosopher(void) {
|
||||||
|
return (*philosophers)[rightPhilosopherNumber()];
|
||||||
|
}
|
||||||
|
void
|
||||||
|
Philosopher::think() {
|
||||||
|
size_t duration = random(100, 1000);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk{printing};
|
||||||
|
std::cout << "Philosopher " << numberOfPhilosopher << " is thinking for " << duration << "." << std::endl;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Philosopher::takeForks() {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk{changingForkState};
|
||||||
|
setState(PhilosopherState::HUNGRY);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk{printing};
|
||||||
|
std::cout << "Philosopher " << numberOfPhilosopher << " is hungry." << std::endl;
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
hasBothForks.acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Philosopher::eat() {
|
||||||
|
size_t duration = random(100, 1000);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk{printing};
|
||||||
|
std::cout << "Philosopher " << numberOfPhilosopher << " is eating." << std::endl;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Philosopher::putForks() {
|
||||||
|
std::lock_guard<std::mutex> lk{changingForkState};
|
||||||
|
state = PhilosopherState::THINKING;
|
||||||
|
leftPhilosopher()->test();
|
||||||
|
rightPhilosopher()->test();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhilosopherState
|
||||||
|
Philosopher::getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Philosopher::Philosopher(ListOfPhilosophersPtr philosophers, int numberOfPhilosopher):
|
||||||
|
state(PhilosopherState::THINKING) {
|
||||||
|
this->numberOfPhilosopher = numberOfPhilosopher;
|
||||||
|
this->philosophers = philosophers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Philosopher::startThread() {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk{printing};
|
||||||
|
std::cout << "Philosopher " << numberOfPhilosopher << " has sit in the table." << std::endl;
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
think();
|
||||||
|
takeForks();
|
||||||
|
eat();
|
||||||
|
putForks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Philosopher::test() {
|
||||||
|
if (state == PhilosopherState::HUNGRY &&
|
||||||
|
leftPhilosopher()->getState() != PhilosopherState::EATING &&
|
||||||
|
rightPhilosopher()->getState() != PhilosopherState::EATING) {
|
||||||
|
setState(PhilosopherState::EATING);
|
||||||
|
hasBothForks.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
src/random.cpp
Normal file
10
src/random.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <random>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
size_t
|
||||||
|
random(size_t min, size_t max)
|
||||||
|
{
|
||||||
|
static std::mt19937 rnd(std::time(nullptr));
|
||||||
|
return std::uniform_int_distribution<>(min, max)(rnd);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user