github.com/haraldrudell/parl@v0.4.176/once-do-err.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parl
     7  
     8  // onceDoErr provides a wrapper function for sync.once.Do
     9  // that executes a function returning an error that may panic
    10  //   - onceDoErr is a tuple value-type
    11  //   - — if used as local variable, function argument or return value,
    12  //     no allocation tajkes place
    13  //   - — taking its address causes allocation
    14  type onceDoErr struct {
    15  	doErrFuncArgument func() (err error)
    16  	// DoErr return value pointers
    17  	didOnce *bool
    18  	isPanic *bool
    19  	errp    *error
    20  	// pointer to observable parl.Once
    21  	//	- has isDone and result fields
    22  	*Once
    23  }
    24  
    25  // invokeDoErrFuncArgument is behind o.once
    26  func (d *onceDoErr) invokeDoErrFuncArgument() {
    27  	// indicate that the once did execute: last action
    28  	defer d.isDone.Store(true)
    29  	var result onceDoErrResult
    30  	defer d.saveResult(&result)
    31  	defer RecoverErr(func() DA { return A() }, &result.err, &result.isPanic)
    32  
    33  	result.err = d.doErrFuncArgument()
    34  }
    35  
    36  // saveResult stores the outcome of a DoErr invocation
    37  func (d *onceDoErr) saveResult(result *onceDoErrResult) {
    38  
    39  	// store result in parl.Once
    40  	d.result.Store(result)
    41  
    42  	// update DoErr return values
    43  	*d.didOnce = true
    44  	*d.isPanic = result.isPanic
    45  	*d.errp = result.err
    46  }