There's probably a crate for this, but I've been looking through all the crates with "lock" in their name and haven't found it . I need a mutex-type lock like
let lok = LockByName::new("lockthisname"); // anything else wanting "lockthisname" will lock
....
// lok gets dropped, lock is unlocked.
Another solution that might work for this use case (fetching named assets to a local cache) could be to use the fs2 crate on the local file path. Unfortunately, I'm not sure how well maintained that crate is.
If a LockByName is dropped while another is locked then you can acquire a new (different) Arc to the same name. I think in order to get this to work the LockByName needs to store a MutexGuard
It's not that it's self-referential. It's closer to a diamond pattern. guard references lok. The returned LockByName references both. Without the clone() call, that's re-using a mutable borrow. With the clone call, though, since lok is an Arc, it seemingly should work. It's not a loop. But no use of clone seems to fix this.
Calling .lock on a clone crates a guard that borrows from the clone. The compiler thus requires the clone to outlive the guard. However the clone is a temporary that is freed by the end of the statement.
If the compiler allowed this, then there's no other way it could prevent the following:
let LockByName { lok, name, guard } = lock;
drop(lok);
// If lok was the last copy then the refcount
// is now zero and the mutex has been freed
*guard; // invoke UB
"Reuse of a mutable borrow" is not the reason why it is impossible to put a mutex and a guard for it on the same struct. After all, as far as the borrow checker is concerned, the mutex has only been borrowed immutably.
This happens with all form of "thing, with another thing that borrows from it".