Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible for the ArcMutexGuard to be more flexible? #328

Open
frank-king opened this issue Mar 10, 2022 · 4 comments
Open

Is it possible for the ArcMutexGuard to be more flexible? #328

frank-king opened this issue Mar 10, 2022 · 4 comments

Comments

@frank-king
Copy link

frank-king commented Mar 10, 2022

I'm using the arc_lock feature and it requires self: &Arc<Self> in the Mutex::lock_arc function. But in my case, it is a little bit inconvenient.

// Foo is usually put in an `Arc`, shared by threads.
// Only part of it needs to be guarded. There are some
// read-only fields such as `id`, which allows direct access
// without lock.
// Foo is considered as public API.
pub struct Foo {
    _impl: Mutex<FooImpl>,
    id: usize, // read-only field
}

// Data in `FooImpl` need to be guarded by a `Mutex`.
struct FooImpl {
    data: ..., // the actual data to be guarded by a `Mutex`,
    another_data: ...,
}

But it is not allowed to call lock_arc for the _impl in a Arc<Foo> because the signature doesn't match.

let foo = Arc::new(FooImpl::new());
let _impl = foo._impl.lock_arc(); // `lock_arc` is not valid here.

I hope the lock_arc could accept anything like this: &Arc<impl AsRef<Self>> where Self is the Mutex type. In that way, if I impl AsRef<Mutex<FooImpl>> for Foo, then I can call Mutex::lock_arc(&*self) to acquire a mutex guard of FooImpl where self's type is &Arc<Foo>.

To extend the lock_arc to lock_arc(this: &Arc<impl AsRef<Self>> may be a break change, but it can be resolved via a different feature gate like arc_lock_ext or rename lock_arc to lock_in_arc or something else.

Do you think it is feasible?

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 10, 2022

What if AsRef returns a different Mutex every time it is called? That would make mutable aliasing possible if lock_arc accepts this: &Arc<impl AsRef<Self>> as two lock calls would lock a different mutex, right?

@frank-king
Copy link
Author

frank-king commented Mar 10, 2022

Oh, it's terrible, I can even construct one using safe rust.

struct Foo {
    impls: [Mutex<FooImpl>; 2],
}

impl AsRef<Mutex<FooImpl>> for Foo {
    fn as_ref(&self) -> &Mutex<FooImpl> {
        static IDX: AtomicUsize = AtomicUsize::new(0);
        &self[IDX.fetch_add(1, Relaxed) % 2]
    }
}

struct FooImpl(u32);

let foo = Foo::new(impls: [Mutex::new(FooImpl(0)), Mutex::new(FooImpl(1))]);

Is it possible to prevent this?

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 10, 2022

I think the only way is to use a new unsafe trait instead of AsRef.

@frank-king
Copy link
Author

An unsafe trait seems feasible. But I can't help asking myself, no safer way? Now how I hope there can be associated fields in traits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants