vak: (Знайка)
Serge Vakulenko ([personal profile] vak) wrote2025-03-02 08:13 pm

Тип RwLock<T>

Тип Mutex<T> хорош, но разрешает доступ нескольким потокам только по очереди. Что если нам чаще требуется только читать объект, а изменять только изредка? Через RwLock<T> можно получить множественный доступ на чтение.

Question: Please show a meaningful C++ implementation of type RwLock<T>.

I'll create a C++ implementation of RwLock<T> similar to Rust's RwLock, which provides a reader-writer lock allowing multiple readers or one writer. We'll use C++'s std::shared_mutex (available since C++17) as the underlying synchronization primitive.

Here's the implementation: rwlock.cpp.
#include <shared_mutex>
#include <memory>

template<typename T>
class RwLock {
private:
T data;
mutable std::shared_mutex mtx; // mutable to allow locking in const methods

public:
// Constructor
explicit RwLock(T value) : data(std::move(value)) {}

// Read guard class (multiple readers allowed)
class ReadGuard {
private:
const T& data_ref;
std::shared_lock<std::shared_mutex> lock;

public:
ReadGuard(const T& d, std::shared_mutex& m)
: data_ref(d), lock(m) {}

const T& operator*() const { return data_ref; }
const T* operator->() const { return &data_ref; }
};

// Write guard class (exclusive writer)
class WriteGuard {
private:
T& data_ref;
std::unique_lock<std::shared_mutex> lock;

public:
WriteGuard(T& d, std::shared_mutex& m)
: data_ref(d), lock(m) {}

T& operator*() { return data_ref; }
T* operator->() { return &data_ref; }
};

// Lock methods
ReadGuard read_lock() const {
return ReadGuard(data, mtx);
}

WriteGuard write_lock() {
return WriteGuard(data, mtx);
}

// Prevent copying
RwLock(const RwLock&) = delete;
RwLock& operator=(const RwLock&) = delete;

// Allow move construction
RwLock(RwLock&&) = default;
RwLock& operator=(RwLock&&) = default;
};
Key components and features:

1. RwLock<T> Class:
  • Uses std::shared_mutex for reader-writer locking
  • Stores the data of type T
  • Marked as mutable to allow read locking in const methods
2. ReadGuard Class:
  • Uses std::shared_lock for shared access
  • Provides read-only access to the data
  • Multiple ReadGuards can exist simultaneously
3. WriteGuard Class:
  • Uses std::unique_lock for exclusive access
  • Provides read-write access to the data
  • Only one WriteGuard can exist at a time
4. Interface:
  • read_lock(): Returns a ReadGuard for reading
  • write_lock(): Returns a WriteGuard for writing
  • Both guards automatically unlock when they go out of scope (RAII)
5. Differences from Rust's RwLock:
  • C++ doesn't have Rust's poisoning mechanism
  • No Result/Option return types (Rust uses these for lock acquisition)
  • Relies on C++ RAII instead of Rust's ownership system
The example demonstrates:
  • Multiple readers can access the data simultaneously
  • Writers get exclusive access
  • Automatic cleanup when guards go out of scope
  • Thread-safe concurrent access
Possible extensions could include:
  • Try-lock variants (try_read_lock, try_write_lock)
  • Timeout-based locking
  • Upgradeable read locks
  • Condition variable support
juan_gandhi: (Default)

[personal profile] juan_gandhi 2025-03-03 10:03 am (UTC)(link)
Ценный класс, но он, похоже, сильно на библиотеку опирается.
Вообще, вся эта классика из статьи Дейкстры, как я понимаю.