Здравствуйте, Patalog, Вы писали:
P>Если еще не, то советую почитать тов. remark, в частности
P>Что такое модель памяти? И с чем её едят?
Да, спасибо, читал.
В моём представлении должно быть как то так: acquire/release на входе/выходе + дополнительное relaxed чтение при блокировке читателем.
class atomic_shared_mutex {
public:
atomic_shared_mutex() : mtx_(0) {}
void lock_shared() {
// изначально читаем в relaxed, барьер будет далее, в CAS операции
int state = mtx_.load(std::memory_order_relaxed);
for(;;) {
if(state < 0) {
// занят писателем - прерываем поток, при возврате перечитываем состояние
std::this_thread::yield();
state = mtx_.load(std::memory_order_relaxed);
}
// не занят, увеличиваем счётчик читателей
else if(mtx_.compare_exchange_weak(state, state+1, std::memory_order_acquire))
break;
}
}
void unlock_shared() {
mtx_.fetch_sub(1, std::memory_order_release);
}
void lock() {
for(;;) {
int state = 0;
if(mtx_.compare_exchange_weak(state, -1, std::memory_order_acquire))
break;
// попытка не удалась, использовали weak CAS, отдадим управление
// только если мьютекс действительно занят
if(state != 0)
std::this_thread::yield();
}
}
void unlock() {
mtx_.store(0, std::memory_order_release);
}
private:
std::atomic<int> mtx_;
};