Documentation
¶
Overview ¶
Package sess provides session-typed communication protocols via algebraic effects on code.hybscloud.com/kont.
Protocols are composed of typed operations dispatched on a session endpoint.
Architecture ¶
- Transport: Lock-free bounded SPSC queues via code.hybscloud.com/lfq. New creates an Endpoint pair.
- Non-blocking: Operations return code.hybscloud.com/iox.ErrWouldBlock on backpressure.
- Execution: Dual-world API supporting closure-based (Cont-world) and defunctionalized (Expr-world) evaluation.
- Error Handling: Session operations are non-blocking, while error operations short-circuit returning code.hybscloud.com/kont.Either.
API Topologies ¶
- Operations: Send, Recv, Close, SelectL, SelectR, Offer. Endpoint delegation is Send/Recv of *Endpoint.
- Cont-world: SendThen, RecvBind, CloseDone, SelectLThen, SelectRThen, OfferBranch.
- Expr-world: Zero-allocation variants like ExprSendThen, ExprRecvBind, etc. Bridge via Reify and Reflect.
- Recursive: Loop and ExprLoop for trampoline-based iterative protocols.
Integration ¶
- Stepping: Step and Advance (or StepError/AdvanceError) evaluate computations one effect at a time, making them easy to integrate with a proactor loop.
- Blocking: Exec, Run (and Error/Expr variants) wait past boundaries using adaptive backoff.
Example ¶
epA, _ := sess.New()
protocol := sess.ExprSendThen(42, sess.ExprCloseDone[struct{}](struct{}{}))
_, susp := sess.Step[struct{}](protocol)
for susp != nil {
var err error
if _, susp, err = sess.Advance(epA, susp); 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. Stack-safe: pure completed steps are iterated without Go stack growth; effectful steps are trampolined through evalFrames via UnwindFrame.
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. Stack-safe: delegates recursion to ExprLoop's iterative trampoline via Reify/Reflect, avoiding Go stack growth on deep pure Left chains.
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.