Суть в том, что чтение из одного блока данных происходит очень часто из разных потоков, но в определенный момент один(заранее заданный поток) может обновить данные, так как код используется в очень критичном месте и обновление данных происходит очень быстро, никакой блокировки с засыпанием быть не должно (mutex, shared_mutex). Написал свой велосипед:
Сама структура:
struct BufferData {
  ...
  volatile std::atomic<bool> m_remapFlag{false}; //флаг, если происходит запись
  volatile std::atomic<std::size_t> m_usageCounter{0}; //количество чтений
};
Блокировка/освобождение на чтение (блокировка на чтение не должно блокировать другое чтение):
BufferData *OGLBuffer::lock() {
  std::shared_ptr<BufferData> ptr;
  if (!m_data.expired()) {
    ptr = m_data.lock();
  } else
    throw std::runtime_error("Buffer page deleted");
  //Ждем пока обновляют данные
  while (ptr->m_remapFlag) {
    continue;
  }
  //Увеличиваем счетчик
  ptr->m_usageCounter++;
  if (!ptr->m_remapFlag) {
    //Если за это время не начали обновлять данные то возвращаем указатель
    return ptr.get();
  } else {
    //Иначе повторяем попытку
    unlock();
    return lock();
  }
//Метод освобождения довольно прост
void OGLBuffer::unlock() { m_data.lock()->m_usageCounter--; }
Теперь блокировка/освобождение на запись:
void OGLPage::lockBuffer(std::size_t const &id) {
  m_buffers[id]->m_remapFlag = true; //Ставим флаг на запись
  //Ждем конца чтений
  while (m_buffers[id]->m_usageCounter > 0) {
    continue;
  }
}
void OGLPage::unlockBuffer(std::size_t const &id) {
  //Чистим флаг
  m_buffers[id]->m_remapFlag = false;
}
Вроде бы не вижу мест где гонка могла бы возникнуть, однако доказать что так и есть, увы, не могу. Хотелось бы услышать комментариев/критики по этому поводу.






