Daily bit(e) C++. std::shared_mutex

Добавлено 30 сентября 2023 в 13:12

Daily bit(e) C++ #15, мьютекс с общими блокировками: std::shared_mutex.

Daily bit(e) C++

std::shared_mutex – это вариант std::mutex из C++14 (C++17 для несинхронизированной версии), который поддерживает два типа блокировок: эксклюзивную блокировку, которая может удерживаться только одним потоком, и общую блокировку. которая может удерживаться любым количеством потоков (пока не удерживается эксклюзивная блокировка).

Это семантика обычно необходима для доступа чтения-записи, поскольку операции чтения могут выполняться параллельно, а операции записи требуют эксклюзивного доступа.

#include <mutex>
#include <shared_mutex>
#include <array>
#include <optional>

struct Data {};
struct RecentSnapshots 
{
    void push(const Data& data) 
    {
        // Мы собираемся изменить данные,
        // захватываем unique_lock
        std::unique_lock lock(mux_);
        buffer_[offset_ % 64] = data;
        ++offset_;
    }
    std::optional<Data> get(size_t index) const 
    {
        // Мы только читаем, но нам нужно
        // предотвратить одновременную запись,
        // захватываем shared_lock
        std::shared_lock lock(mux_);
        if (index >= offset_)
            return std::nullopt;
        if (offset_ >= 64 && offset_-64 > index)
            return std::nullopt;
        return buffer_[index % 64];
    }
    size_t min_offset() const 
    {
        // Мы только читаем, но нам нужно
        // предотвратить одновременную запись,
        // захватываем shared_lock
        std::shared_lock lock(mux_);
        if (offset_ <= 64) return 0;
        return offset_ - 64;
    }
private:
    // Нам нужен mutable, так как мы изменяем
    // состояние этого мьютекса (захватом блокировки)
    // в константных методах.
    mutable std::shared_mutex mux_;
    std::array<Data,64> buffer_;
    size_t offset_ = 0;
};

// Примечание: вызов min_offset() с последующим get(offset)
// НЕ обеспечивает никакой транзакционности, поскольку
// запись может вставить себя между двумя этими вызовами.

Открыть пример на Compiler Explorer.

Теги

C++ / CppDaily bit(e) C++Mutex / МьютексSTL / Standard Template Library / Стандартная библиотека шаблоновМногопоточностьПрограммирование

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.