Adding first commit.

This commit is contained in:
Sergiotarxz 2023-04-19 00:32:59 +02:00
commit e234a48faf
8 changed files with 267 additions and 0 deletions

7
Doxyfile Normal file
View 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

View File

@ -0,0 +1,7 @@
#pragma once
enum class PhilosopherState {
THINKING,
HUNGRY,
EATING,
};

63
include/philosopher.hpp Normal file
View 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
View File

@ -0,0 +1,4 @@
#pragma once
#include <cstddef>
size_t
random(size_t min, size_t max);

31
meson.build Normal file
View 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
View 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
View 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
View 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);
}