waiter

package
v0.0.0-...-b9252dc Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2024 License: Apache-2.0, MIT Imports: 1 Imported by: 289

Documentation

Overview

Package waiter provides the implementation of a wait queue, where waiters can be enqueued to be notified when an event of interest happens.

Becoming readable and/or writable are examples of events. Waiters are expected to use a pattern similar to this to make a blocking function out of a non-blocking one:

func (o *object) blockingRead(...) error {
	err := o.nonBlockingRead(...)
	if err != ErrAgain {
		// Completed with no need to wait!
		return err
	}

	e := createOrGetWaiterEntry(...)
	o.EventRegister(&e, waiter.EventIn)
	defer o.EventUnregister(&e)

	// We need to try to read again after registration because the
	// object may have become readable between the last attempt to
	// read and read registration.
	err = o.nonBlockingRead(...)
	for err == ErrAgain {
		wait()
		err = o.nonBlockingRead(...)
	}

	return err
}

Another goroutine needs to notify waiters when events happen. For example:

func (o *object) Write(...) ... {
	// Do write work.
	[...]

	if oldDataAvailableSize == 0 && dataAvailableSize > 0 {
		// If no data was available and now some data is
		// available, the object became readable, so notify
		// potential waiters about this.
		o.Notify(waiter.EventIn)
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AlwaysReady

type AlwaysReady struct {
}

AlwaysReady implements the Waitable interface but is always ready. Embedding this struct into another struct makes it implement the boilerplate empty functions automatically.

func (*AlwaysReady) EventRegister

func (*AlwaysReady) EventRegister(*Entry) error

EventRegister doesn't do anything because this object doesn't need to issue notifications because its readiness never changes.

func (*AlwaysReady) EventUnregister

func (*AlwaysReady) EventUnregister(e *Entry)

EventUnregister doesn't do anything because this object doesn't need to issue notifications because its readiness never changes.

func (*AlwaysReady) Readiness

func (*AlwaysReady) Readiness(mask EventMask) EventMask

Readiness always returns the input mask because this object is always ready.

type ChannelNotifier

type ChannelNotifier chan struct{}

ChannelNotifier is a simple channel-based notification.

func (ChannelNotifier) NotifyEvent

func (c ChannelNotifier) NotifyEvent(EventMask)

NotifyEvent implements waiter.EventListener.NotifyEvent.

type Entry

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

Entry represents a waiter that can be add to the a wait queue. It can only be in one queue at a time, and is added "intrusively" to the queue with no extra memory allocations.

+stateify savable

func NewChannelEntry

func NewChannelEntry(mask EventMask) (e Entry, ch chan struct{})

NewChannelEntry initializes a new Entry that does a non-blocking write to a struct{} channel when the callback is called. It returns the new Entry instance and the channel being used.

func NewFunctionEntry

func NewFunctionEntry(mask EventMask, fn func(EventMask)) (e Entry)

NewFunctionEntry initializes a new Entry that calls the given function.

func (*Entry) Init

func (e *Entry) Init(eventListener EventListener, mask EventMask)

Init initializes the Entry.

This must only be called when unregistered.

func (*Entry) Mask

func (e *Entry) Mask() EventMask

Mask returns the entry mask.

func (*Entry) NotifyEvent

func (e *Entry) NotifyEvent(mask EventMask)

NotifyEvent notifies the event listener.

Mask should be the full set of active events.

type EventListener

type EventListener interface {
	// NotifyEvent is the function to be called when the waiter entry is
	// notified. It is responsible for doing whatever is needed to wake up
	// the waiter.
	//
	// The callback is supposed to perform minimal work, and cannot call
	// any method on the queue itself because it will be locked while the
	// callback is running.
	//
	// The mask indicates the events that occurred and that the entry is
	// interested in.
	NotifyEvent(mask EventMask)
}

EventListener provides a notify callback.

type EventMask

type EventMask uint64

EventMask represents io events as used in the poll() syscall.

const (
	EventIn       EventMask = 0x01   // POLLIN
	EventPri      EventMask = 0x02   // POLLPRI
	EventOut      EventMask = 0x04   // POLLOUT
	EventErr      EventMask = 0x08   // POLLERR
	EventHUp      EventMask = 0x10   // POLLHUP
	EventRdNorm   EventMask = 0x0040 // POLLRDNORM
	EventWrNorm   EventMask = 0x0100 // POLLWRNORM
	EventInternal EventMask = 0x1000
	EventRdHUp    EventMask = 0x2000 // POLLRDHUP

	AllEvents      EventMask = 0x1f | EventRdNorm | EventWrNorm | EventRdHUp
	ReadableEvents EventMask = EventIn | EventRdNorm
	WritableEvents EventMask = EventOut | EventWrNorm
)

Events that waiters can wait on. The meaning is the same as those in the poll() syscall.

func EventMaskFromLinux

func EventMaskFromLinux(e uint32) EventMask

EventMaskFromLinux returns an EventMask representing the supported events from the Linux events e, which is in the format used by poll(2).

func (EventMask) ToLinux

func (e EventMask) ToLinux() uint32

ToLinux returns e in the format used by Linux poll(2).

type NeverReady

type NeverReady struct {
}

NeverReady implements the Waitable interface but is never ready. Otherwise, this is exactly the same as AlwaysReady.

func (*NeverReady) EventRegister

func (*NeverReady) EventRegister(e *Entry) error

EventRegister doesn't do anything because this object doesn't need to issue notifications because its readiness never changes.

func (*NeverReady) EventUnregister

func (*NeverReady) EventUnregister(e *Entry)

EventUnregister doesn't do anything because this object doesn't need to issue notifications because its readiness never changes.

func (*NeverReady) Readiness

func (*NeverReady) Readiness(mask EventMask) EventMask

Readiness always returns the input mask because this object is always ready.

type Queue

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

Queue represents the wait queue where waiters can be added and notifiers can notify them when events happen.

The zero value for waiter.Queue is an empty queue ready for use.

+stateify savable

func (*Queue) EventRegister

func (q *Queue) EventRegister(e *Entry)

EventRegister adds a waiter to the wait queue.

func (*Queue) EventUnregister

func (q *Queue) EventUnregister(e *Entry)

EventUnregister removes the given waiter entry from the wait queue.

func (*Queue) Events

func (q *Queue) Events() EventMask

Events returns the set of events being waited on. It is the union of the masks of all registered entries.

func (*Queue) IsEmpty

func (q *Queue) IsEmpty() bool

IsEmpty returns if the wait queue is empty or not.

func (*Queue) Notify

func (q *Queue) Notify(mask EventMask)

Notify notifies all waiters in the queue whose masks have at least one bit in common with the notification mask.

type Waitable

type Waitable interface {
	// Readiness returns what the object is currently ready for. If it's
	// not ready for a desired purpose, the caller may use EventRegister and
	// EventUnregister to get notifications once the object becomes ready.
	//
	// Implementations should allow for events like EventHUp and EventErr
	// to be returned regardless of whether they are in the input EventMask.
	Readiness(mask EventMask) EventMask

	// EventRegister registers the given waiter entry to receive
	// notifications when an event occurs that makes the object ready for
	// at least one of the events in mask.
	EventRegister(e *Entry) error

	// EventUnregister unregisters a waiter entry previously registered with
	// EventRegister().
	EventUnregister(e *Entry)
}

Waitable contains the methods that need to be implemented by waitable objects.

Jump to

Keyboard shortcuts

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