
Context.pudu
Pudu91 lines3.9 KB
1/** @Mediator.Context.Carrier — per-message cancellation token and typed items */2module PuduLangMediator.Context34import Std.Concurrent.Cancel as Cancel5import Std.HashMap as HashMap6import PuduLangMediator as Messaging7import PuduLangMediator.Utils.Erasure as Erasure8import PuduLangMediator.Utils.Shared as Shared910/** @Mediator.Context.Context — what one message carries through its pipeline */11export type Context = { token: Cancel.Token, items: Shared.Shared[HashMap.HashMap[Str, Erasure.Packed]] }1213/** @Mediator.Context.Key — a typed name for one item */14export type Key[T] = { name: Str, slot: Erasure.Slot[T] }151617export fn create() -> Context { Context{token: Cancel.token(), items: Shared.shared(HashMap.empty())} }181920export fn cancellable(token: Cancel.Token) -> Context { Context{..create(), token: token} }212223export fn withToken(source: &Context, token: Cancel.Token) -> Context { Context{..*source, token: token} }24252627export fn expiring(source: &Context, millis: Int) -> Context { withToken(source, Cancel.childExpiring(&source.token, millis)) }28293031export fn key[T](name: Str) -> Key[T] { Key{name: name, slot: Erasure.slot()} }323334export fn set[T](target: &Context, name: &Key[T], value: T) -> () {35 let packed = Erasure.pack(&name.slot, value)36 let field = name.name37 Shared.update(&target.items, fn(held: HashMap.HashMap[Str, Erasure.Packed]) -> HashMap.HashMap[Str, Erasure.Packed] {38 HashMap.insert(&held, field, packed)39 })40}414243export fn get[T](source: &Context, name: &Key[T]) -> Option[T] {44 let packed = HashMap.get(&Shared.current(&source.items), &name.name) ?45 Erasure.unpack(&name.slot, &packed)46}474849export fn getOr[T](source: &Context, name: &Key[T], fallback: T) -> T {50 match get(source, name) {51 case Some(found) => found52 case None => fallback53 }54}555657export fn has[T](source: &Context, name: &Key[T]) -> Bool { HashMap.containsKey(&Shared.current(&source.items), &name.name) }585960export fn remove[T](target: &Context, name: &Key[T]) -> () {61 let field = name.name62 Shared.update(&target.items, fn(held: HashMap.HashMap[Str, Erasure.Packed]) -> HashMap.HashMap[Str, Erasure.Packed] {63 HashMap.remove(&held, &field)64 })65}666768export fn names(source: &Context) -> Array[Str] { HashMap.keys(&Shared.current(&source.items)) }697071export fn cancel(target: &Context, why: Str) -> () { let _cancelled = Cancel.cancel(&target.token, why) }727374export fn stopped(source: &Context) -> Bool { Cancel.stopped(&source.token) }757677export fn check[E](source: &Context) -> Result[(), Messaging.Failure[E]] {78 match Cancel.check(&source.token) {79 case Ok(_) => Ok(())80 case Err(why) => Err(Messaging.Cancelled(Cancel.explain(&why)))81 }82}838485export fn pause[E](source: &Context, millis: Int) -> Result[(), Messaging.Failure[E]] {86 match Cancel.pause(&source.token, millis) {87 case Ok(_) => Ok(())88 case Err(why) => Err(Messaging.Cancelled(Cancel.explain(&why)))89 }90}91