Documentation
¶
Overview ¶
Package sess provides session-typed communication protocols via algebraic effects on code.hybscloud.com/kont.
Protocols are composed from typed operations, each dispatched as an algebraic effect on a session endpoint.
Design ¶
- Lock-free bounded transport via code.hybscloud.com/lfq SPSC queues
- Non-blocking code.hybscloud.com/iox.ErrWouldBlock boundary semantics
- Dual-world API: Cont-world (closure-based) and Expr-world (defunctionalized)
- Structural interface dispatch for session operations
Non-Blocking Semantics ¶
Session operations are strictly non-blocking. Operations directly query the underlying transport and return code.hybscloud.com/iox.ErrWouldBlock when backpressure limits are reached:
- nil error: operation completed
- code.hybscloud.com/iox.ErrWouldBlock: queue not ready, retry after peer progress
The stepping API (Step, Advance) preserves this boundary. Blocking helpers (Exec, Run) use code.hybscloud.com/iox.Backoff to wait past the boundary.
Session Operations ¶
Six operations define the protocol vocabulary. Each implements DispatchSession with non-blocking semantics:
- Send: Send a typed value to the peer
- Recv: Receive a typed value from the peer
- Close: Signal session termination (never blocks)
- SelectL: Choose the left branch
- SelectR: Choose the right branch
- Offer: Wait for the peer's branch choice
Endpoint delegation is Send/Recv of *Endpoint.
Cont-World API ¶
Fused constructors compose operations with continuation sequencing: SendThen, RecvBind, CloseDone, SelectLThen, SelectRThen, OfferBranch.
Expr-World API ¶
Defunctionalized constructors mirror the Cont-world API with pooled frames for amortized zero-allocation evaluation: ExprSendThen, ExprRecvBind, ExprCloseDone, ExprSelectLThen, ExprSelectRThen, ExprOfferBranch.
Recursive Protocols ¶
Loop and ExprLoop express recursive protocols via tailRecM. The step function returns Left(nextState) to continue or Right(result) to finish.
Execution ¶
Blocking helpers wait past code.hybscloud.com/iox.ErrWouldBlock via adaptive backoff:
- Exec, ExecExpr: Run a protocol on a pre-created endpoint
- Run, RunExpr: Create a pair and interleave both sides cooperatively
Stepping / Proactor Integration ¶
One-effect-at-a-time evaluation for external runtimes:
- Step: Evaluate a protocol until the first effect suspension
- Advance: Dispatch the suspended operation (non-blocking)
Unconsumed suspensions from code.hybscloud.com/iox.ErrWouldBlock are retryable. code.hybscloud.com/kont.Suspension.Op returns the concrete operation for protocol-aware scheduling.
Error Handling ¶
Composed session+error dispatch: session operations are non-blocking, error operations (code.hybscloud.com/kont.ThrowError, code.hybscloud.com/kont.CatchError) short-circuit. Results are code.hybscloud.com/kont.Either — Right on success, Left on Throw.
- ExecError, ExecErrorExpr: Blocking error execution
- RunError, RunErrorExpr: Blocking dual error execution
- StepError: Step with error support
- AdvanceError: Advance with error support
Cont ↔ Expr Bridge ¶
Transport ¶
New creates a connected Endpoint pair using four bounded SPSC queues (two data, two choice) from code.hybscloud.com/lfq.
Serial ¶
Each session pair receives a monotonically increasing Serial. Both endpoints share the same serial.
Example (Stepping) ¶
epA, _ := sess.New()
protocol := sess.ExprSendThen(42, sess.ExprCloseDone[struct{}](struct{}{}))
_, susp := sess.Step[struct{}](protocol)
for susp != nil {
var err error
_, susp, err = sess.Advance(epA, susp)
if err != nil {
continue // retry on ErrWouldBlock
}
}
Index ¶
- func Advance[R any](ep *Endpoint, susp *kont.Suspension[R]) (R, *kont.Suspension[R], error)
- func AdvanceError[E, R any](ep *Endpoint, susp *kont.Suspension[kont.Either[E, R]]) (kont.Either[E, R], *kont.Suspension[kont.Either[E, R]], error)
- func CloseDone[A any](a A) kont.Eff[A]
- func Exec[R any](ep *Endpoint, protocol kont.Eff[R]) R
- func ExecError[E, R any](ep *Endpoint, protocol kont.Eff[R]) kont.Either[E, R]
- func ExecErrorExpr[E, R any](ep *Endpoint, protocol kont.Expr[R]) kont.Either[E, R]
- func ExecExpr[R any](ep *Endpoint, protocol kont.Expr[R]) R
- func ExprCloseDone[A any](a A) kont.Expr[A]
- func ExprLoop[S, A any](initial S, step func(S) kont.Expr[kont.Either[S, A]]) kont.Expr[A]
- func ExprOfferBranch[A any](onLeft func() kont.Expr[A], onRight func() kont.Expr[A]) kont.Expr[A]
- func ExprRecvBind[T, B any](f func(T) kont.Expr[B]) kont.Expr[B]
- func ExprSelectLThen[B any](next kont.Expr[B]) kont.Expr[B]
- func ExprSelectRThen[B any](next kont.Expr[B]) kont.Expr[B]
- func ExprSendThen[T, B any](v T, next kont.Expr[B]) kont.Expr[B]
- func Loop[S, A any](initial S, step func(S) kont.Eff[kont.Either[S, A]]) kont.Eff[A]
- func New() (*Endpoint, *Endpoint)
- func OfferBranch[A any](onLeft func() kont.Eff[A], onRight func() kont.Eff[A]) kont.Eff[A]
- func RecvBind[T, B any](f func(T) kont.Eff[B]) kont.Eff[B]
- func Reflect[A any](m kont.Expr[A]) kont.Eff[A]
- func Reify[A any](m kont.Eff[A]) kont.Expr[A]
- func Run[A, B any](a kont.Eff[A], b kont.Eff[B]) (A, B)
- func RunError[E, A, B any](a kont.Eff[A], b kont.Eff[B]) (kont.Either[E, A], kont.Either[E, B])
- func RunErrorExpr[E, A, B any](a kont.Expr[A], b kont.Expr[B]) (kont.Either[E, A], kont.Either[E, B])
- func RunExpr[A, B any](a kont.Expr[A], b kont.Expr[B]) (A, B)
- func SelectLThen[B any](next kont.Eff[B]) kont.Eff[B]
- func SelectRThen[B any](next kont.Eff[B]) kont.Eff[B]
- func SendThen[T, B any](v T, next kont.Eff[B]) kont.Eff[B]
- func Step[R any](protocol kont.Expr[R]) (R, *kont.Suspension[R])
- func StepError[E, R any](protocol kont.Expr[R]) (kont.Either[E, R], *kont.Suspension[kont.Either[E, R]])
- type Close
- type Endpoint
- type Offer
- type Recv
- type SelectL
- type SelectR
- type Send
- type Serial
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Advance ¶
func Advance[R any](ep *Endpoint, susp *kont.Suspension[R]) (R, *kont.Suspension[R], error)
Advance dispatches the suspended session operation on the endpoint. DispatchSession is non-blocking: returns iox.ErrWouldBlock when the bounded SPSC queue cannot make progress (the I/O boundary).
On success (nil error), the suspension is consumed and the protocol advances to the next effect or completion. On iox.ErrWouldBlock, the suspension is unconsumed and may be retried after the peer makes progress.
func AdvanceError ¶
func AdvanceError[E, R any](ep *Endpoint, susp *kont.Suspension[kont.Either[E, R]]) (kont.Either[E, R], *kont.Suspension[kont.Either[E, R]], error)
AdvanceError dispatches the suspended operation on the endpoint. Session ops are non-blocking (ErrWouldBlock). Error ops are eager: Throw discards the suspension and returns Left.
func Exec ¶
Exec runs a Cont-world session protocol on a pre-created endpoint. Blocks on iox.ErrWouldBlock via adaptive backoff (iox.Backoff), without spawning goroutines or creating channels.
func ExecError ¶
ExecError runs a Cont-world session protocol with error handling on a pre-created endpoint. Returns Either[E, R] — Right on success, Left on Throw. Blocks on iox.ErrWouldBlock via adaptive backoff (iox.Backoff), without spawning goroutines or creating channels.
func ExecErrorExpr ¶
ExecErrorExpr runs an Expr-world session protocol with error handling on a pre-created endpoint. Returns Either[E, R] — Right on success, Left on Throw. Blocks on iox.ErrWouldBlock via adaptive backoff (iox.Backoff), without spawning goroutines or creating channels.
func ExecExpr ¶
ExecExpr runs an Expr-world session protocol on a pre-created endpoint. Blocks on iox.ErrWouldBlock via adaptive backoff (iox.Backoff), without spawning goroutines or creating channels.
func ExprCloseDone ¶
ExprCloseDone closes the session and returns a. Fuses ExprPerform(Close{}) + ExprThen + ExprReturn.
func ExprLoop ¶
ExprLoop runs a recursive session protocol (Expr-world). step returns Left(nextState) to continue or Right(result) to finish. Fuses ExprBind inline to avoid the type-erasing wrapper closure.
func ExprOfferBranch ¶
ExprOfferBranch waits for the peer's choice and calls onLeft or onRight. Fuses ExprPerform(Offer{}) + ExprBind + Either branch.
func ExprRecvBind ¶
ExprRecvBind receives a value and passes it to f. Fuses ExprPerform(Recv[T]{}) + ExprBind.
func ExprSelectLThen ¶
ExprSelectLThen selects the left branch and continues with next. Fuses ExprPerform(SelectL{}) + ExprThen.
func ExprSelectRThen ¶
ExprSelectRThen selects the right branch and continues with next. Fuses ExprPerform(SelectR{}) + ExprThen.
func ExprSendThen ¶
ExprSendThen sends a value and then continues with next. Fuses ExprPerform(Send[T]{Value: v}) + ExprThen.
func Loop ¶
Loop runs a recursive session protocol (Cont-world). step returns Left(nextState) to continue or Right(result) to finish.
func New ¶
New creates a connected pair of session endpoints. Internal transport uses bounded lock-free SPSC queues: two for data (A→B, B→A), two for branch choice (A→B, B→A), and a shared atomic counter for close signaling.
Session operations are non-blocking: DispatchSession returns iox.ErrWouldBlock when the peer has not yet produced or consumed.
func OfferBranch ¶
OfferBranch waits for the peer's choice and calls onLeft or onRight. Fuses Perform(Offer{}) + Bind + Either branch.
func Reflect ¶
Reflect converts an Expr-world session protocol to Cont-world. The resulting Eff can be evaluated with Exec or Run.
func Reify ¶
Reify converts a Cont-world session protocol to Expr-world. The resulting Expr can be evaluated with ExecExpr, RunExpr, or stepped with Step and Advance.
func Run ¶
Run creates a session pair, runs both Cont-world protocols, and returns both results. Interleaves execution of both sides on the calling goroutine using adaptive backoff (iox.Backoff) when neither side can make progress. Does not spawn goroutines or create channels.
func RunError ¶
RunError creates a session pair, runs both Cont-world protocols with error handling, and returns both results as Either values. Interleaves execution of both sides on the calling goroutine using adaptive backoff (iox.Backoff). Does not spawn goroutines or create channels.
func RunErrorExpr ¶
func RunErrorExpr[E, A, B any](a kont.Expr[A], b kont.Expr[B]) (kont.Either[E, A], kont.Either[E, B])
RunErrorExpr creates a session pair, runs both Expr-world protocols with error handling, and returns both results as Either values. Interleaves execution of both sides on the calling goroutine using adaptive backoff (iox.Backoff). Does not spawn goroutines or create channels.
func RunExpr ¶
RunExpr creates a session pair, runs both Expr-world protocols, and returns both results. Interleaves execution of both sides on the calling goroutine using adaptive backoff (iox.Backoff) when neither side can make progress. Does not spawn goroutines or create channels.
func SelectLThen ¶
SelectLThen selects the left branch and continues with next. Fuses Perform(SelectL{}) + Then.
func SelectRThen ¶
SelectRThen selects the right branch and continues with next. Fuses Perform(SelectR{}) + Then.
func SendThen ¶
SendThen sends a value and then continues with next. Fuses Perform(Send[T]{Value: v}) + Then.
func Step ¶
func Step[R any](protocol kont.Expr[R]) (R, *kont.Suspension[R])
Step evaluates a session protocol until the first effect suspension. Returns (result, nil) on completion, or (zero, suspension) if pending.
func StepError ¶
func StepError[E, R any](protocol kont.Expr[R]) (kont.Either[E, R], *kont.Suspension[kont.Either[E, R]])
StepError evaluates a session protocol with error support until the first effect suspension. Returns (Either[E, R], nil) on completion or error, or (zero, suspension) if pending.
Types ¶
type Close ¶
Close is the effect operation for closing the session. Perform(Close{}) signals session termination.
type Endpoint ¶
type Endpoint struct {
// contains filtered or unexported fields
}
Endpoint represents one side of a session-typed channel pair. Transport is backed by bounded lock-free SPSC queues from lfq.
type Offer ¶
Offer is the effect operation for receiving a branch choice from the peer. Perform(Offer{}) receives the peer's Left or Right selection.
type Recv ¶
Recv is the effect operation for receiving a value of type T. Perform(Recv[T]{}) receives a typed value from the peer.
type SelectL ¶
SelectL is the effect operation for choosing the left branch. Perform(SelectL{}) signals the left choice to the peer.
type SelectR ¶
SelectR is the effect operation for choosing the right branch. Perform(SelectR{}) signals the right choice to the peer.