`Arc>` and `MutexGuard` pack

⚓ Rust    📅 2025-09-04    👤 surdeus    👁️ 2      

surdeus

I am not good at English. Sorry if there are any funny expressions.


My situation

I have Arc<Mutex<T>> and MutexGuard<'a, T> from it.
I want to hold MutexGuard for a while, instead of repeatedly acquiring and releasing it.
And I want to pass MutexGuard between functions.

My Attempt

If I carry only MutexGuard, the reference count of Arc might drop to zero at some time.
To prevent this, it seems that I need a type that packs both Arc and MutexGuard together.

Code with unsafe

Following is my code. Oh! there is unsafe...
I almost always mistake with it.
Moreover, this time is more creepy.
Because this seems like a common situation to me.
Please let me know if there are any mistakes.

use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, MutexGuard};

fn main() {
    let var = Arc::new(Mutex::new(1));
    let mut ag = sub(&var);
    *ag += 1;
    assert_eq!(*ag, 2);
}

fn sub<T>(var: &Arc<Mutex<T>>) -> ArcGuard<'_, T> {
    ArcGuard::new(&var)
}

struct ArcGuard<'a, T: 'a> {
    _arc: Arc<Mutex<T>>,
    guard: MutexGuard<'a, T>,
}

impl<'a, T: 'a> ArcGuard<'a, T> {
    pub fn new(arc: &Arc<Mutex<T>>) -> Self {
        let arc = arc.clone();
        let arc_ptr = &arc as *const Arc<Mutex<T>>;
        let guard = unsafe { (&*arc_ptr).lock().unwrap() };
        Self {
            _arc: arc,
            guard,
        }
    }
}

impl<'a, T: 'a> Deref for ArcGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        &*self.guard
    }
}

impl<'a, T: 'a> DerefMut for ArcGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut *self.guard
    }
}

5 posts - 3 participants

Read full topic

🏷️ Rust_feed