-
Notifications
You must be signed in to change notification settings - Fork 29
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
Support a shared Semaphor #9
Comments
The reason this is not included is that I actually imagined a composition through What would be the use-case where the external Arc isn’t sufficient? |
Say you had: struct Foo {
sema: Arc<Semaphore>,
}
impl Foo {
async fn bar(&self) -> Bar {
Bar {
permits: self.sema.acquire(1).await,
}
}
}
struct Bar {
permits: SemaphoreReleaser<???>,
} What would be the lifetime of the You could put a copy of the semaphore in |
It would have a lifetime of // Acquire one or more permits, e.g. to limit resources
let _releaser = self.sema.acquire(1).await;
do_another_async_action_which_needs_to_be_guarded().await;
drop(_releaser); // or implicit drop The store permits and release elsewhere use-case is more rare. But nevertheless it exists - that's why the explicit struct ArcReleaser {
sem: Arc<Semaphore>,
permits: usize,
}
impl ArcReleaser {
fn from_releaser(releaser: SemaphoreReleaser, sem: Arc<Semaphore>) -> ArcReleaser {
let permits = releaser.disarm(); // Take over commits
ArcReleaser {
sem,
permits,
}
}
impl Drop for ArcReleaser {
fn drop(&mut self) {
self.sem.release(self.permits);
}
}
async fn your_async_fn() {
let releaser = arc_sem.acquire(1).await;
let arc_releaser = ArcReleaser::from_releaser(releaser, arc_sem.clone());
// Can now move around arc_releaser without lifetime
} I am aware that's more boilerplate than a builtin |
Yep, but as far as I know you can't enforce a 'self lifetime.
Sure that would work. I agree that the code-duplication is quite horrendous. My use case is to implement a bounded channel where each element has arbitrary weight (in bytes). Its pretty usefull when doing I/O. I don't know if that's considered a rare use-case. I guess I'll write a small wrapper based on you suggestion. |
That's actually a great use for an async semaphore! I required something similar recently, where I wanted to give various streams a flow-control budget. I however had use-cases where I could not use
Sounds good. I will close your PR then. SemaphoreReleaser::to_owned(self, sem: Arc<Semaphore>) -> ArcSemaphoreReleaser which is like a compromise on between duplicating it in every application and adding a full shared semaphore with all the duplication to the library. But I think I want to wait for a bit more of experiences/application usages on this. Adding the few lines to projects which need it isn't too bad to make it work. |
A
Semaphore
with aSemaphoreReleaser
without a lifetime parameter would be quite useful. I imagine that using a design similar tochannel::shared
would do the trick.The text was updated successfully, but these errors were encountered: