Task: Dining philosophers


C++: #include <algorithm>
#include <array>
#include <chrono>
#include <iostream>
#include <mutex>
#include <random>
#include <string>
#include <string_view>
#include <thread>

const int timeScale = 42;  

void Message(std::string_view message)
{
    
    static std::mutex cout_mutex;
    std::scoped_lock cout_lock(cout_mutex);
    std::cout << message << std::endl;
}

struct Fork {
    std::mutex mutex;
};

struct Dinner {
    std::array<Fork, 5> forks;
    ~Dinner() { Message("Dinner is over"); }
};

class Philosopher
{
    
    
    std::mt19937 rng{std::random_device {}()};

    const std::string name;
    Fork& left;
    Fork& right;
    std::thread worker;

    void live();
    void dine();
    void ponder();
public:
    Philosopher(std::string name_, Fork& l, Fork& r)
    : name(std::move(name_)), left(l), right(r), worker(&Philosopher::live, this)
    {}
    ~Philosopher()
    {
        worker.join();
        Message(name + " went to sleep.");
    }
};

void Philosopher::live()
{
    for(;;) 
    {
        {
            
            
            std::scoped_lock dine_lock(left.mutex, right.mutex);

            dine();

            
        }
        
        ponder();
    }
}

void Philosopher::dine()
{
    Message(name + " started eating.");

    
    thread_local std::array<const char*, 3> foods {"chicken", "rice", "soda"};
    thread_local std::array<const char*, 3> reactions {
        "I like this %s!", "This %s is good.", "Mmm, %s..."
    };
    thread_local std::uniform_int_distribution<> dist(1, 6);
    std::shuffle(    foods.begin(),     foods.end(), rng);
    std::shuffle(reactions.begin(), reactions.end(), rng);
    
    constexpr size_t buf_size = 64;
    char buffer[buf_size];
    for(int i = 0; i < 3; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(dist(rng) * timeScale));
        snprintf(buffer, buf_size, reactions[i], foods[i]);
        Message(name + ": " + buffer);
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(dist(rng)) * timeScale);

    Message(name + " finished and left.");
}

void Philosopher::ponder()
{
    static constexpr std::array<const char*, 5> topics {{
        "politics", "art", "meaning of life", "source of morality", "how many straws makes a bale"
    }};
    thread_local std::uniform_int_distribution<> wait(1, 6);
    thread_local std::uniform_int_distribution<> dist(0, topics.size() - 1);
    while(dist(rng) > 0) {
        std::this_thread::sleep_for(std::chrono::milliseconds(wait(rng) * 3 * timeScale));
        Message(name + " is pondering about " + topics[dist(rng)] + ".");
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(wait(rng) * 3 * timeScale));
    Message(name + " is hungry again!");
}

int main()
{
    Dinner dinner;
    Message("Dinner started!");
    
    std::array<Philosopher, 5> philosophers {{
            {"Aristotle",   dinner.forks[0], dinner.forks[1]},
            {"Democritus",  dinner.forks[1], dinner.forks[2]},
            {"Plato",       dinner.forks[2], dinner.forks[3]},
            {"Pythagoras",  dinner.forks[3], dinner.forks[4]},
            {"Socrates",    dinner.forks[4], dinner.forks[0]},
    }};
    Message("It is dark outside...");
}







VB: 




Public Const HOLDON = False
Public Const DIJKSTRASOLUTION = True
Public Const X = 10 
Public Const GETS = 0
Public Const PUTS = 1
Public Const EATS = 2
Public Const THKS = 5
Public Const FRSTFORK = 0
Public Const SCNDFORK = 1
Public Const SPAGHETI = 0
Public Const UNIVERSE = 1
Public Const MAXCOUNT = 100000
Public Const PHILOSOPHERS = 5
Public semaphore(PHILOSOPHERS - 1) As Integer
Public positi0n(1, PHILOSOPHERS - 1) As Integer
Public programcounter(PHILOSOPHERS - 1) As Long
Public statistics(PHILOSOPHERS - 1, 5, 1) As Long
Public names As Variant
Private Sub init()
    names = [{"Aquinas","Babbage","Carroll","Derrida","Erasmus"}]
    For j = 0 To PHILOSOPHERS - 2
        positi0n(0, j) = j + 1 
        positi0n(1, j) = j     
    Next j
    If DIJKSTRASOLUTION Then
        positi0n(0, PHILOSOPHERS - 1) = j 
        positi0n(1, PHILOSOPHERS - 1) = 0 
    Else
        positi0n(0, PHILOSOPHERS - 1) = 0 
        positi0n(1, PHILOSOPHERS - 1) = j 
    End If
End Sub
Private Sub philosopher(subject As Integer, verb As Integer, objekt As Integer)
    statistics(subject, verb, objekt) = statistics(subject, verb, objekt) + 1
    If verb < 2 Then
        If semaphore(positi0n(objekt, subject)) <> verb Then
            If Not HOLDON Then
                
                
                semaphore(positi0n(FRSTFORK, subject)) = 1 - objekt
                
                programcounter(subject) = 0
            End If
        Else
            
            semaphore(positi0n(objekt, subject)) = 1 - verb
            programcounter(subject) = (programcounter(subject) + 1) Mod 6
        End If
    Else
        
        
        programcounter(subject) = IIf(X * Rnd > 1, verb, verb + 1) Mod 6
    End If
End Sub
Private Sub dine()
    Dim ph As Integer
    Do While TC < MAXCOUNT
        For ph = 0 To PHILOSOPHERS - 1
            Select Case programcounter(ph)
                Case 0: philosopher ph, GETS, FRSTFORK
                Case 1: philosopher ph, GETS, SCNDFORK
                Case 2: philosopher ph, EATS, SPAGHETI
                Case 3: philosopher ph, PUTS, FRSTFORK
                Case 4: philosopher ph, PUTS, SCNDFORK
                Case 5: philosopher ph, THKS, UNIVERSE
            End Select
            TC = TC + 1
        Next ph
    Loop
End Sub
Private Sub show()
    Debug.Print "Stats", "Gets", "Gets", "Eats", "Puts", "Puts", "Thinks"
    Debug.Print "", "First", "Second", "Spag-", "First", "Second", "About"
    Debug.Print "", "Fork", "Fork", "hetti", "Fork", "Fork", "Universe"
    For subject = 0 To PHILOSOPHERS - 1
        Debug.Print names(subject + 1),
        For objekt = 0 To 1
            Debug.Print statistics(subject, GETS, objekt),
        Next objekt
        Debug.Print statistics(subject, EATS, SPAGHETI),
        For objekt = 0 To 1
            Debug.Print statistics(subject, PUTS, objekt),
        Next objekt
        Debug.Print statistics(subject, THKS, UNIVERSE)
    Next subject
End Sub
Public Sub main()
    init
    dine
    show
End Sub