flow

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package flow provides pull-based frame pacing for the compose library.

The compositor uses a Controller to decide when to request frames from each connected module. This implements the Wayland frame callback pattern: modules render only when the compositor asks, preventing them from flooding the compositor with unsolicited frames.

The controller is passive (no goroutines, no timers). The compositor's render loop polls Controller.ShouldRequest on each tick and calls Controller.FrameRequested after sending a request to a module. When a frame arrives, the compositor calls Controller.FrameDelivered. If a module fails to respond in time, Controller.FrameMissed adaptively reduces the effective request rate.

All exported methods are safe for concurrent use from multiple goroutines. The package is standalone with no internal dependencies.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Controller

type Controller struct {
	// contains filtered or unexported fields
}

Controller manages pull-based frame pacing for connected modules. The compositor uses it to decide when to request frames from each module. All methods are safe for concurrent access from multiple goroutines.

func New

func New(opts ...Option) *Controller

New creates a flow controller. Use WithClock to inject a custom time source for testing.

func (*Controller) AddModule

func (c *Controller) AddModule(moduleID uint64, fps uint16)

AddModule registers a module with its preferred FPS. If fps is 0, it defaults to 1 FPS (suitable for static content like a clock).

func (*Controller) FrameDelivered

func (c *Controller) FrameDelivered(moduleID uint64)

FrameDelivered marks that a frame was received from the specified module. Resets the pending flag, records the delivery time, and clears the missed count. If the module ID does not exist, this is a no-op.

func (*Controller) FrameMissed

func (c *Controller) FrameMissed(moduleID uint64)

FrameMissed marks that the specified module failed to deliver a frame in time. After missedThreshold (3) consecutive misses, the controller halves the effective request rate by doubling the interval. This prevents wasting bandwidth on slow or stuck modules. If the module ID does not exist, this is a no-op.

func (*Controller) FrameRequested

func (c *Controller) FrameRequested(moduleID uint64)

FrameRequested marks that a FrameRequest was sent to the specified module. Records the request time and sets the pending flag. If the module ID does not exist, this is a no-op.

func (*Controller) ModuleCount

func (c *Controller) ModuleCount() int

ModuleCount returns the total number of registered modules.

func (*Controller) PendingModules

func (c *Controller) PendingModules() int

PendingModules returns the count of modules with pending (unanswered) frame requests.

func (*Controller) RemoveModule

func (c *Controller) RemoveModule(moduleID uint64)

RemoveModule unregisters a module. If the module ID does not exist, this is a no-op.

func (*Controller) ShouldRequest

func (c *Controller) ShouldRequest(moduleID uint64) bool

ShouldRequest returns true if it is time to request a frame from the specified module. The compositor should call this on each render tick.

Returns false if:

  • The module ID is not registered
  • A request is already pending (module has not responded yet)
  • Not enough time has elapsed since the last request (respecting target FPS and adaptive rate reduction)

type Option

type Option func(*Controller)

Option configures a Controller.

func WithClock

func WithClock(fn func() time.Time) Option

WithClock sets a custom time source for the controller. Intended for testing to provide deterministic time progression without time.Sleep.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL