-
Notifications
You must be signed in to change notification settings - Fork 31
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
feature request: try_rcu / some return value to the caller of rcu #94
Comments
Hello To be honest, I kind of don't understand what you're trying to say/accomplish. Maybe you could sketch the signature of that Does it help that the bool changed = false;
as.rcu(|i| if (*i > 10) { i } else { changed = true; *i + 1 });
if changed { ... } Anyway, sometimes I feel like the |
I've been using the following extension trait for a while to implement pub trait ArcSwapExt<T> {
/// [`ArcSwap::rcu`](arc_swap::ArcSwap::rcu), but with Result that short-circuits on error.
fn try_rcu<R, F, E>(&self, f: F) -> Result<T, E>
where
F: FnMut(&T) -> Result<R, E>,
R: Into<T>;
}
impl<T, S> ArcSwapExt<T> for arc_swap::ArcSwapAny<T, S>
where
T: arc_swap::RefCnt,
S: arc_swap::strategy::CaS<T>,
{
fn try_rcu<R, F, E>(&self, mut f: F) -> Result<T, E>
where
F: FnMut(&T) -> Result<R, E>,
R: Into<T>,
{
fn ptr_eq<Base, A, B>(a: A, b: B) -> bool
where
A: arc_swap::AsRaw<Base>,
B: arc_swap::AsRaw<Base>,
{
let a = a.as_raw();
let b = b.as_raw();
std::ptr::eq(a, b)
}
let mut cur = self.load();
loop {
let new = f(&cur)?.into();
let prev = self.compare_and_swap(&*cur, new);
let swapped = ptr_eq(&*cur, &*prev);
if swapped {
return Ok(arc_swap::Guard::into_inner(prev));
} else {
cur = prev;
}
}
}
} ArcSwap's API has been stable for years, so was this code. Would be nice to move it here, but it's not a big deal to keep it around like that. My use case is fallible updates. For example, adding an item to a persistent collection wrapped in ArcSwap or failing and not changing anything if that's a duplicate. |
Hmm, now I see the purpose. My little worry here is, if it works for So I have to wonder if:
None of them looks like the ideal solution, but I'm open to your views on what to do here. |
I don't have a strong opinion on the details, other than it would just be nice to have the feature. Result is more general than Option - Result<T, ()> can model an Option, but not vice versa, so my suggestion would be to either implement just Result until Try is stable, and then revisit after stabilisation. |
OK, that's fair. That being said, I'm not 100% sure extanding that Would you send a PR? (And sorry that my answer took so long, too many other things to attend to…) |
Sometimes the closure passed to rcu() needs to be observable to the caller.
e.g.
But this is clearly racy as we are re-reading.
I would love to be able to do:
or some similar construct, where the computation within the closure is able to signal to the caller.
Would you like a patch?
The text was updated successfully, but these errors were encountered: