Please review my RwLock :)
⚓ Rust 📅 2026-03-03 👤 surdeus 👁️ 3I am trying to write an RwLock to understand atomics and memory ordering. This obviously a bad implementation and the very first problem that I've noticed is: If I call read and write concurrently from two separate threads, the call to write may execute between the load and store present inside read which is a problem...could you please suggest a solution for this?
also, please point out other aspects I could improve. Thanks!
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::Relaxed;
pub struct Rw<T> {
data: UnsafeCell<T>,
writeable: AtomicBool,
readable: AtomicBool,
}
unsafe impl<T> Send for Rw<T> where T: Send {}
unsafe impl<T> Sync for Rw<T> where T: Send + Sync {}
impl<T> Rw<T> {
pub fn new(data: T) -> Self {
Self {
data: UnsafeCell::new(data),
writeable: AtomicBool::new(true),
readable: AtomicBool::new(true),
}
}
pub fn read<'read>(&'read self) -> RwReadGuard<'read, T> {
while !self.readable.load(Relaxed) {
std::hint::spin_loop();
}
self.writeable.store(false, Relaxed);
RwReadGuard { rw: self }
}
pub fn write<'write>(&'write self) -> RwWriteGuard<'write, T> {
while self
.writeable
.compare_exchange_weak(true, false, Relaxed, Relaxed)
.is_err()
{
std::hint::spin_loop();
}
self.readable.store(false, Relaxed);
RwWriteGuard { rw: self }
}
}
pub struct RwReadGuard<'read, T> {
rw: &'read Rw<T>,
}
impl<T> Deref for RwReadGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.rw.data.get() }
}
}
impl<T> Drop for RwReadGuard<'_, T> {
fn drop(&mut self) {
self.rw.writeable.store(true, Relaxed);
}
}
pub struct RwWriteGuard<'write, T> {
rw: &'write Rw<T>,
}
impl<T> Deref for RwWriteGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.rw.data.get() }
}
}
impl<T> DerefMut for RwWriteGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.rw.data.get() }
}
}
impl<T> Drop for RwWriteGuard<'_, T> {
fn drop(&mut self) {
self.rw.readable.store(true, Relaxed);
self.rw.writeable.store(true, Relaxed);
}
}
2 posts - 2 participants
🏷️ Rust_feed