error[E0515]: cannot return value referencing temporary value
|
27 | self.cache.read().unwrap().get(key)
| --------------------------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
Neither clone() nor cloned() on the Option returned by get() fixes this.
I don't understand why the fn owns the data. What is returned is an Option<&V>, an Option holding a reference to a value owned by the Map (cache).
The Map implementation itself does something seemingly totally analogous with get; from map.rs:
You will never be able to return an unprotected bare reference to data protected by a lock.
Returning &V is unsafe, because it doesn't stop the cache from being modified at the same time and e.g. delete the item that you've returned reference to.
You can return RwLockGuard that will keep the lock locked.
Alternatively, you can wrap values in Arc and non-borrowed Arc.
A lock can't give you a shared loan valid for the entire existence of the data under the lock, since that data can be changed and deleted using the lock.
The lock will only let you borrow data for as long as it's locked, by tying that lifetime to the lifetime of the lock guard.
The lock guard is created in the function, and when you get &V, it's set up to borrow from the lock guard via Deref trait.
The Rust ecosystem, for reasons unbeknownst to be, has decided that it's ideal for a crate not to advance into or past 1.0, no matter how mature. You'll find several well-used crates on 0.x.y.
Yeah, crates unwilling to go to 1.0.0 is a wider Rust ecosystem problem. You have to resort to other means to figure out how "good" or "finished" or "stable" a crate is.
This one happens to be quite good.
libs.rs says #1 in Concurrency, 12,981,895 downloads per month, 2,889 direct dependents. Good start. Last release was in May. The readme says:
The current minimum required Rust version is 1.56. Any change to this is considered a breaking change and will require a major version bump.
That sort of MSRV policy is usually a sign of being popular.
The repo owner is Amanieu, and you can see they're involved with rust-lang crates and reviews... clicks on one. Oh look, they're on the libs team. Team leader, even. If we can't trust them we've got bigger problems.
If you want to continue vetting from there you could check out some reviews, use crev, look at the code yourself... typical painstaking dependency audit stuff.
As an outside observer, take my analysis with a grain of salt. I haven't seen any direct discussion of this, but I've been looking into the implementation for a while now. The standard library Mutex is designed to be a thin wrapper around the OS mutex, but your mileage may vary by operating system. I assume the concern would be support for systems which don't have time locks. On Linux, Android, BSD and Windows 10, it's based on futexes, which makes it very fast, and could allow for a timed lock implementation. It's pretty similar to the parking lot implementation. Apple systems only got futexes last year, so the standard library still uses pthread_mutex_t, which also supports timed locks. Windows 7 doesn't have futexes, so instead the Win32 SRWLock is used, which doesn't support timed locks.
Theoretically, this shouldn't affect RwLock, because Windows 7 uses a custom queue implementation that is similar to but not reliant upon SRWLock (SRWLock has a bug which can cause undefined behavior for RwLock). I don't think any other platforms would have a problem here, and I don't see any reason why the queue implementation couldn't be extended to use park_timeout to make timed locks work. But it would be weird to implement timed locks for RwLock but not Mutex. Implementing a new mutex for Windows 7 is also non-ideal, but that's really the only thing preventing it. Condvar already implements wait_timeout, so there's not an especially good philosophical reason to avoid it. Someone could argue that there might be a target in the future which needs to be supported but doesn't have timed locks, but even C11 has timed locks. I think it's far more reasonable to have timed locks than Once::wait[1], which is currently in nightly. I would consider making an RFC for it. I haven't read the entirety of Tracking issue for improving std::sync::{Mutex, RwLock, Condvar} · Issue #93740 · rust-lang/rust · GitHub, so maybe there's some discussion there. Otherwise the biggest blocker is Windows 7 and 8's implementation of Mutex.
That's not to imply that Once::wait is a bad idea ↩︎