Multithreaded access to Arc without Mutex

⚓ Rust    📅 2026-03-28    👤 surdeus    👁️ 2      

surdeus

Hi 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

Read full topic

🏷️ Rust_feed