Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

once.gno

2.15 Kb · 100 lines
  1// Package once provides utilities for one-time execution patterns.
  2// It extends the concept of sync.Once with error handling and panic options.
  3package once
  4
  5import (
  6	"errors"
  7)
  8
  9// Once represents a one-time execution guard
 10type Once struct {
 11	done    bool
 12	err     error
 13	paniced bool
 14	value   any // stores the result of the execution
 15}
 16
 17// New creates a new Once instance
 18func New() *Once {
 19	return &Once{}
 20}
 21
 22// Do executes fn only once and returns nil on subsequent calls
 23func (o *Once) Do(fn func()) {
 24	if o.done {
 25		return
 26	}
 27	defer func() { o.done = true }()
 28	fn()
 29}
 30
 31// DoErr executes fn only once and returns the same error on subsequent calls
 32func (o *Once) DoErr(fn func() error) error {
 33	if o.done {
 34		return o.err
 35	}
 36	defer func() { o.done = true }()
 37	o.err = fn()
 38	return o.err
 39}
 40
 41// DoOrPanic executes fn only once and panics on subsequent calls
 42func (o *Once) DoOrPanic(fn func()) {
 43	if o.done {
 44		panic("once: multiple execution attempted")
 45	}
 46	defer func() { o.done = true }()
 47	fn()
 48}
 49
 50// DoValue executes fn only once and returns its value, subsequent calls return the cached value
 51func (o *Once) DoValue(fn func() any) any {
 52	if o.done {
 53		return o.value
 54	}
 55	defer func() { o.done = true }()
 56	o.value = fn()
 57	return o.value
 58}
 59
 60// DoValueErr executes fn only once and returns its value and error
 61// Subsequent calls return the cached value and error
 62func (o *Once) DoValueErr(fn func() (any, error)) (any, error) {
 63	if o.done {
 64		return o.value, o.err
 65	}
 66	defer func() { o.done = true }()
 67	o.value, o.err = fn()
 68	return o.value, o.err
 69}
 70
 71// Reset resets the Once instance to its initial state
 72// This is mainly useful for testing purposes
 73func (o *Once) Reset() {
 74	o.done = false
 75	o.err = nil
 76	o.paniced = false
 77	o.value = nil
 78}
 79
 80// IsDone returns whether the Once has been executed
 81func (o *Once) IsDone() bool {
 82	return o.done
 83}
 84
 85// Error returns the error from the last execution if any
 86func (o *Once) Error() error {
 87	return o.err
 88}
 89
 90var (
 91	ErrNotExecuted = errors.New("once: not executed yet")
 92)
 93
 94// Value returns the stored value and an error if not executed yet
 95func (o *Once) Value() (any, error) {
 96	if !o.done {
 97		return nil, ErrNotExecuted
 98	}
 99	return o.value, nil
100}