У меня есть класс Buffer
, который реализует шаблон двойного буфера , разработанный с учетом многопоточности:
class Buffer {
public:
void write(size_t idx, float value) {
std::lock_guard<std::mutex> lk(mut);
(*next)[idx] = value; // write to next buffer
}
float read(size_t idx) const {
std::lock_guard<std::mutex> lk(mut);
return (*current)[idx]; // read from current buffer
}
void swap() noexcept {
std::lock_guard<std::mutex> lk(mut);
std::swap(current, next); // swap pointers
}
Buffer() : buf0(32), buf1(32), current(&buf0), next(&buf1) { }
private:
std::vector<float> buf0, buf1; // two buffers
std::vector<float> *current, *next;
mutable std::mutex mut;
};
Этот класс содержит два буфера. Доступ к буферам всегда осуществляется через указатели:
- Буфер, в котором выполняется чтение, указывается указателем
current
. - Буфер, в который производится запись, указывается указателем
next
.
Будет два потока: поток обновления будет записывать в следующий буфер, вызывающий метод write
, поток чтения будет читать из текущего буфера, вызывая метод read
. Когда поток обновления завершен, он вызывает swap
, чтобы поменять указатели на буферы.
Перестановка буферов должна быть сделана атомарно , поэтому мне нужно заблокировать мьютекс в каждом методе (создание объекта lk
).
Проблема заключается в том, что блокировка мьютекса в каждом методе не позволяет двум потокам одновременно обращаться к соответствующему буферу. Но два буфера независимы: нет проблем, если один поток изменяет один буфер, а другой поток читает другой буфер.
Я хочу разрешить обновляющему потоку изменять свой буфер в то же время, когда считывающий поток читает свой соответствующий буфер. Есть ли способ добиться этого?