GithubHelp home page GithubHelp logo

Comments (5)

Matthias247 avatar Matthias247 commented on June 24, 2024

The reason this is not included is that I actually imagined a composition through Arc<Semaphore> being sufficient. Channels have dedicated shared types to be able to split senders and receivers and to be able to hide them easier behind traits. But for Mutex/Semaphore/Event I didn’t see a need for it.

What would be the use-case where the external Arc isn’t sufficient?

from futures-intrusive.

jean-airoldie avatar jean-airoldie commented on June 24, 2024

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 SemaphoreReleaser? If its static, then bar borrows Foo for static. If its not static then Bar cannot be used on a separate thread.

You could put a copy of the semaphore in Bar and make Bar a self referencing struct, but that seems overly complicated.

from futures-intrusive.

Matthias247 avatar Matthias247 commented on June 24, 2024

It would have a lifetime of 'self. Or actually it would be a little bit more messy, due to how lifetime interference in async fns works. I agree that if you want to store the releaser somewhere else, it isn't ideal. However it's not the typical use-case of the semaphore. That one is more like:

// 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 release and disarm methods exist. Would they be applicable for your use-case in combination with Arc<Semaphore>? You use them together with a custom releaser type to keep the RAII semantics.

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 shared type. However as you discovered the code-duplication for adding those types isn't ideal, and I would prefer to keep the library surface as small and maintainable as possible.

from futures-intrusive.

jean-airoldie avatar jean-airoldie commented on June 24, 2024

It would have a lifetime of 'self. Or actually it would be a little bit more messy, due to how lifetime interference in async fns works.

Yep, but as far as I know you can't enforce a 'self lifetime.

Would they be applicable for your use-case in combination with Arc?

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.

from futures-intrusive.

Matthias247 avatar Matthias247 commented on June 24, 2024

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.

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 Arcs for that purpose (due to pure no-std) and therefore stored the permits as plain number.

I guess I'll write a small wrapper based on you suggestion.

Sounds good. I will close your PR then.
Maybe it makes sense to include the code from above as

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.

from futures-intrusive.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.