Adding first commit.
This commit is contained in:
commit
e234a48faf
|
@ -0,0 +1,7 @@
|
|||
GENERATE_HTML=yes
|
||||
EXTRACT_ALL=yes
|
||||
RECURSIVE=yes
|
||||
INPUT=../include
|
||||
DISABLE_INDEX = YES
|
||||
GENERATE_TREEVIEW = YES
|
||||
PROJECT_NAME=dining-philosophers
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
enum class PhilosopherState {
|
||||
THINKING,
|
||||
HUNGRY,
|
||||
EATING,
|
||||
};
|
||||
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <cstddef>
|
||||
size_t
|
||||
random(size_t min, size_t max);
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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