moonbitstack/moonzero/syncx does not have a README file

    Inflight

    type Inflight[T]

    One key's call: the waiters' condition, and the answer once it is known.

    Once

    pub struct Once {
    done : Bool
    }

    A body that runs at most once: the first caller runs it, every later one is a no-op. Guards one-time initialisation, which in a service is a pool, a table or a connection that must not be built twice.

    Once::done

    fn Once::done(self : Once) -> Bool

    Whether the body has run.

    Once::new

    fn Once::new() -> Once

    A body that has not run yet.

    Once::run

    fn Once::run(self : Once, body : () -> Unit) -> Bool

    Run body unless it has already run, and report whether this call ran it.

    Pool

    pub struct Pool[T] {
    make : () -> T
    idle : Array[T]
    }

    A pool of reusable objects: a caller takes one, uses it, and hands it back. Building is deferred until the first take, so a pool nobody touches costs nothing — which is what makes it usable for a buffer or a connection that only some code paths need.

    Pool::get

    fn[T] Pool::get(self : Pool[T]) -> T

    Take an object: an idle one when there is one, a fresh one otherwise.

    Pool::idle

    fn[T] Pool::idle(self : Pool[T]) -> Int

    How many objects are idle.

    Pool::new

    fn[T] Pool::new(make : () -> T) -> Pool[T]

    A pool that builds its objects with make.

    Pool::put

    fn[T] Pool::put(self : Pool[T], item : T) -> Unit

    Hand an object back. The pool keeps every one it is given, so a caller that wants a ceiling on retained objects puts one on its own side.

    Single

    pub struct Single[T] {
    inflight : Map[String, Inflight[T]]
    }

    One call in flight per key: a second caller asking for the same key while the first is still running waits for that answer instead of issuing a second call, and every one of them receives the same result — or the same failure.

    This is the primitive a cache-aside store is built on: a miss under load must put one query on the database, not one per request.

    Single::len

    fn[T] Single::len(self : Single[T]) -> Int

    The number of calls in flight, which is also the number of keys being shared.

    Single::new

    fn[T] Single::new() -> Single[T]

    An empty group: no call in flight.

    Single::run

    async fn[T] Single::run(self : Single[T], key : String, body : async () -> T) -> T

    Run body for key, or wait for the call already running for it.

    The caller that runs the body is the one that answers everyone; a body that raises answers them all with the same error, so a failing lookup is not retried once per waiter.