i'm trying implement readers writers solution in c++ std::thread.
i create several reader-threads run in infinite loop, pausing time in between each read access. tried recreate algorithm presented in tanenbaum's book of operating systems:
rc_mtx.lock(); // lock incrementing readcount read_count += 1; if (read_count == 1) // if first reader db_mtx.lock(); // make lock on database rc_mtx.unlock(); cell_value = data_base[cell_number]; // read data database rc_mtx.lock(); read_count -= 1; // when finished 'sign reader off' if (read_count == 0) // if last 1 db_mtx.unlock(); // release lock on database mutex rc_mtx.unlock();
of course, problem thread might satisfy condition of being last reader (and therefore want unlock) has never acquired db_mtx
. tried open 'mother' thread readers take care of acquiring , releasing mutex, go lost during process. if there elegant way overcome issue (thread might try release mutex has never been acquired) in elegant way i'd love hear!
you can use condition variable pause writers if readers in progress, instead of using separate lock.
// --- read code rw_mtx.lock(); // block if there write in progress read_count += 1; // announce intention read rw_mtx.unlock(); cell_value = data_base[cell_number]; rw_mtx.lock(); read_count -= 1; // announce intention read if (read_count == 0) rw_write_q.notify_one(); rw_mtx.unlock(); // --- write code std::unique_lock<std::mutex> rw_lock(rw_mtx); write_count += 1; rw_write_q.wait(rw_lock, []{return read_count == 0;}); data_base[cell_number] = cell_value; write_count -= 1; if (write_count > 0) rw_write_q.notify_one();
this implementation has fairness issue, because new readers can cut in front of waiting writers. fair implementation involve proper queue allow new readers wait behind waiting writers, , new writers wait behind waiting readers.
in c++14, can use shared_timed_mutex
instead of mutex
achieve multiple readers/single writer access.
// --- read code std::shared_lock<std::shared_timed_mutex> read_lock(rw_mtx); cell_value = data_base[cell_number]; // --- write code std::unique_lock<std::shared_timed_mutex> write_lock(rw_mtx); data_base[cell_number] = cell_value;
there plain shared_mutex
implementation in next c++ standard (probably c++17).