Documentation
¶
Overview ¶
Package loop is the network domain's event-loop engine (ADR 0186): the native backends a plaintext stream group runs on when it is served by a corenet.LoopHandler — epoll on every Linux architecture, io_uring after a staged probe of the running kernel — and nothing else of the SDK.
It is a leaf below server (§D3): it imports internal/core/net, the shared UnsupportedPlatform of internal/core/proc and the kernel, never server. server binds or adopts the listeners, keeps the lifecycle, the admission and the drain, and hands the loop duplicated descriptors through one type, Listener. The portable backend stays in server: it needs the netpoller.
A loop is one goroutine locked to its OS thread, owning its rings or its epoll instance. Its connection table is pointer-free Go memory the race detector sees; every byte the kernel reads or writes — the read arena, the spill and output slab — is mapped outside the Go heap (§D7). The engine knows bytes, references, deadlines, write pressure and the order of writes; it speaks no HTTP.
An idle connection on a native backend costs at most 256 bytes of Go heap — its slot and its timer link — and no mapped byte: its output chunk is attached at its first Write and returned once drained.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckCapabilities ¶ added in v0.26.28
CheckCapabilities refuses a LoopValue.Capabilities entry the group cannot opt into: an engine, a class B capability or an unknown token, with LoopCapabilityRefused naming it (ADR 0189). A class A-kernel entry needs no opt-in and is accepted as it is. server calls it for the portable backend, which never reaches Start.
func ResolveLoops ¶ added in v0.26.36
ResolveLoops resolves LoopValue.Loops n and says where the count came from, as LoopStateValue.LoopsSource spells it: LoopsAuto is GOMAXPROCS less one read now, at least one, "auto" — the P left over runs the rest of the process (ADR 0199); a positive count is its own, "explicit"; anything else is one, "single" (R8). server calls it once per group, at Start, and keeps the snapshot for every backend.
func Unprobed ¶ added in v0.26.28
func Unprobed(backend string, disabled []corenet.Capability, disabledBy string) []corenet.CapabilityValue
Unprobed is the capability report of a group that runs on backend without the leaf's probes — the portable backend: every row unprobed, or disabled by what the operator switched off, as disabledBy says (ADR 0189).
Types ¶
type Config ¶
type Config struct {
// Group is the group's name, for the start line and State.
Group string
// Value is the group's LoopValue.
Value corenet.LoopValue
// MaxConns is LimitsValue.MaxConns: past it a connection is accepted and
// closed at once. Zero sets no ceiling.
MaxConns int
// IdleTimeout closes a connection with no traffic for that long, its
// output sent. Zero sets none.
IdleTimeout time.Duration
// Handler is the group's loop handler.
Handler corenet.LoopHandler
// Busy reports whether a connection of a lane waits on its worker (the
// chain's LoopOffloader.Pending, R3): the drain keeps it open, eviction
// passes it by. Nil when nothing offloads.
Busy func(lane int, ref corenet.LoopConnRef) bool
// Listeners are the sockets to accept on.
Listeners []Listener
// Log receives the one start line; nil is standard error.
Log io.Writer
// Disabled are the capabilities the operator switched off: never probed,
// never used, reported "disabled" (ADR 0189).
Disabled []corenet.Capability
// DisabledBy says how they were switched off in State; empty is
// KITSUNIUM_NET_DISABLE.
DisabledBy string
// LoopsSource is where Value.Loops came from, for State, when server
// resolved it already: LoopsAuto read as GOMAXPROCS is "auto". Empty lets
// the group say it itself.
LoopsSource string
// contains filtered or unexported fields
}
Config is what server gives a loop group to start: the group's name, its LoopValue, the two options the engine honours itself — MaxConns and IdleTimeout — its handler and its listeners.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group is a running loop group: its loops, their threads and their rings. Start is the one way to get one, so a Group always runs, or ran and was stopped by Shutdown or Close.
func Start ¶
Start resolves cfg against the effective RLIMIT_NOFILE — refusing with LoopNoDescriptors when it is zero or unreadable, before the one ring formula divides by it — starts the group's loops on the backend cfg asks for, and writes one line to cfg.Log naming the backend, the probe stage, any fallback reason, the loops, the rings and their sizes. The listeners are the group's from the call on, started or refused. An explicit backend the platform has no mechanic for is UnsupportedPlatform; one the kernel's probe refused is LoopBackendUnavailable.
func (*Group) Shutdown ¶
Shutdown drains the group, until ctx is done; then it closes the rest. The drain stops accepting without resetting a connection the kernel already completed: every loop cancels its pending accepts — serving one that completed as the cancel crossed it —, takes the listen queue until it is empty, until 65536 connections came from one listener — arrivals outpacing the drain —, or until descriptors run out with no connection of the group left whose close would free one, the rest of the queue reset by the close then; the last loop to take closes the listener. Then each connection closes once it settled, its output sent, a connection that has sent nothing yet once it has or stayed silent for a second. A drain cut short returns DrainTimeout.
func (*Group) State ¶
func (g *Group) State() corenet.LoopStateValue
State reports the group's backend and every ring's counters.