Тип RwLock<T>
2025-03-02 20:13![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Тип 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.
1. RwLock<T> Class:
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.
Key components and features:#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;
};
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
- Uses std::shared_lock for shared access
- Provides read-only access to the data
- Multiple ReadGuards can exist simultaneously
- Uses std::unique_lock for exclusive access
- Provides read-write access to the data
- Only one WriteGuard can exist at a time
- 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)
- 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
- Multiple readers can access the data simultaneously
- Writers get exclusive access
- Automatic cleanup when guards go out of scope
- Thread-safe concurrent access
- Try-lock variants (try_read_lock, try_write_lock)
- Timeout-based locking
- Upgradeable read locks
- Condition variable support