Multithreaded access to Arc without Mutex
⚓ Rust 📅 2026-03-28 👤 surdeus 👁️ 2Hi all,
I am new to Rust, but am enjoying it so far. Thanks for the work put into the community.
I have a data-structure problem that I would like more experienced peoples' opinion on re: complex "atomic" data types.
Essentially, what I would like is a double-buffer type that writes via one thread, and reads via the other thread.
My first implementation looks something like this:
pub struct DoubleBufT<const PRE_N: usize, const POST_N: usize> {
buff_: [SingleBufT<PRE_N, POST_N>; 2],
write_active_buffer_idx_: usize,
read_active_buffer_idx_: usize,
}
impl<const PRE_N: usize, const POST_N: usize> DoubleBufT<PRE_N, POST_N> {
pub fn default() -> Self{
Self {
buff_: core::array::from_fn(|_| SingleBufT::<PRE_N, POST_N>::default()),
write_active_buffer_idx_: 0,
read_active_buffer_idx_: 1,
}
}
pub fn switch_buffer(& mut self){
self.write_active_buffer_idx_ = if self.write_active_buffer_idx_ == 0 {1} else {0};
self.read_active_buffer_idx_ = if self.write_active_buffer_idx_ == 0 {1} else {0};
self.buff_[self.write_active_buffer_idx_].set_full(false); // just switched buffers, it is empty now
}
pub fn write_to_buff(&mut self, all_angles_frame: Vec<Mat>){
self.buff_[self.write_active_buffer_idx_].write_to_buff(all_angles_frame);
}
pub fn read_from_buff(&self, frame_nr: usize) -> (Vec<Mat>, usize, usize) {
let mut frames: Vec<Mat> = vec![];
let mut special_frame_nr: usize = 0;
let mut num_frames_in_seq: usize = 0;
frames = (self.buff_[self.read_active_buffer_idx_]).get_ref_to_frame(frame_nr).to_vec();
special_frame_nr = self.buff_[self.read_active_buffer_idx_].get_current_pre_capacity();
num_frames_in_seq = self.buff_[self.read_active_buffer_idx_].get_current_pre_capacity() + self.buff_[self.read_active_buffer_idx_].get_current_post_capacity();
(frames, special_frame_nr, num_frames_in_seq)
}
where access to the buffers is by creating Arc<Mutex<DoubleBufT>>
However, I have realised that this means that the write thread will block the read thread and vice-versa, as the lock has to be held when doing either reading or writing.
What I would prefer, is that a mutex is internally contained within the DoubleBuffer, and it is grabbed only when switching the buffer indices, or when reading.
I have attempted to modify the struct above to instead contain a mutex, and use it to lock when switching and reading only, however, when I create Arc instead of Arc<Mutex<...>>, understandably, the compiler tells me that DerefMut trait is not implemented for my DoubleBufT.
Other posts such as this one Trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<_>` - #2 by alice recommend that either a mutex (presumably external) is required, or the actor pattern is used. Is there no third option?
Thanks for reading!
5 posts - 3 participants
🏷️ Rust_feed