0

I'm trying to solve a dinning philosophers problem using chandy-misra algorithm. More explanation here: https://en.wikipedia.org/wiki/Dining_philosophers_problem

I'm using one mutex to lock the modified variables and another with condition variable to notify when the fork is free to use.

I can't see the reason why all my philosophers are eating at the same time - they are not waiting for forks other at all. It seems like I'm using mutexes wrong.

Philosopher thread:

void philosopher::dine() {
    while(!is_initialized); // here threads waits until all other philosophers are initialized                                                
    while(!is_stopped) {
        eat();
        think(); // here just sleeps for a few seconds
    }
}

Eat method:

void philosopher::eat() {
    left_fork.request(index);
    right_fork.request(index);

    std::lock(right_fork.get_mutex(), left_fork.get_mutex());                
    std::lock_guard<std::mutex> l1( right_fork.get_mutex(), std::adopt_lock );    
    std::lock_guard<std::mutex> l2( left_fork.get_mutex(), std::adopt_lock );

    int num = distribution(mt);
    std::cout << "Philsopher " << index << " eats for " << num 
               << "seconds." << std::endl;
    sleep(num);
    right_fork.free();
    left_fork.free();
}

How fork class looks:

enum fork_state {
    CLEAN, DIRTY
};

class fork_t {
    int index;
    int owner_id;
    mutable std::mutex condition_m;
    std::mutex owner_m;
    std::condition_variable condition;

    public:
    fork_t(int _index,int _owner_id);
    fork_t(const fork_t &f);
    void request(int phil_req);
    void free();
    std::mutex &get_mutex() { return owner_m; }
    fork_t& operator=(fork_t const &f);
};

void fork_t::request(int phil_req) {

    while (owner_id != phil_req ) {

        std::unique_lock<std::mutex> l(condition_m);

        if(state == DIRTY) {
            std::lock_guard<std::mutex> lock(owner_m);            
            state = CLEAN;
            owner_id = phil_req;
        } else {
            while(state == CLEAN) {
               std::cout<<"Philosopher " << phil_req << " is waiting for"<< index <<std::endl;
                condition.wait(l);
            }
        }
    }
}

void fork_t::free() {
    state = DIRTY;
    condition.notify_one();
}

At the start all forks are given to philosophers with lower id. I would be grateful for any tips.

undershad
  • 1
  • 1
  • 1
    Please provide a [mcve] – 463035818_is_not_an_ai May 11 '19 at 21:55
  • `while(!is_initialized);` Nope. This is undefined behaviour, and the compiler is allowed to do anything it wants with this. Maybe you mean to lock before each test of that variable? Related: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm – UKMonkey May 12 '19 at 02:46

0 Answers0