github.com/haraldrudell/parl@v0.4.176/iters/simple-func.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package iters 7 8 import ( 9 "github.com/haraldrudell/parl/internal/cyclebreaker" 10 ) 11 12 // Function traverses a function generating values 13 type SimpleFunc[T any] struct { 14 // IteratorFunction is a function that can be used with function iterator 15 // - if isCancel true, it means this is the last invocation of IteratorFunction and 16 // IteratorFunction should release any resources. 17 // Any returned value is not used 18 // - IteratorFunction signals end of values by returning parl.ErrEndCallbacks. 19 // if hasValue true, the accompanying value is used 20 // - if IteratorFunction returns error, it will not be invoked again. 21 // Any returned value is not used 22 // - IteratorFunction must be thread-safe 23 // - IteratorFunction is invoked by at most one thread at a time 24 iteratorFunction SimpleIteratorFunc[T] 25 // BaseIterator implements the DelegateAction[T] function required by 26 // Delegator[T] and Cancel 27 // - provides its delegateAction method to Delegator 28 *BaseIterator[T] 29 } 30 31 // NewFunctionIterator returns an [Iterator] iterating over a function 32 // - thread-safe 33 func NewSimpleFunctionIterator[T any]( 34 iteratorFunction SimpleIteratorFunc[T], 35 asyncCancel ...func(), 36 ) (iterator Iterator[T]) { 37 if iteratorFunction == nil { 38 panic(cyclebreaker.NilError("iteratorFunction")) 39 } 40 f := &SimpleFunc[T]{iteratorFunction: iteratorFunction} 41 f.BaseIterator = NewBaseIterator[T](f.iteratorAction, asyncCancel...) 42 return f 43 } 44 45 // Init implements the right-hand side of a short variable declaration in 46 // the init statement for a Go “for” clause 47 // 48 // Usage: 49 // 50 // for i, iterator := NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { 51 // // i is pointer to slice element 52 func (i *SimpleFunc[T]) Init() (iterationVariable T, iterator Iterator[T]) { 53 iterator = i 54 return 55 } 56 57 // baseIteratorRequest invokes fn recovering a possible panic 58 // - if cancelState == notCanceled, a new value is requested. 59 // Otherwise, iteration cancel is requested 60 // - if err is nil, value is valid and isPanic false. 61 // Otherwise, err is non-nil and isPanic may be set. 62 // value is zero-value 63 // - thread-safe but invocations must be serialized 64 func (i *SimpleFunc[T]) iteratorAction(isCancel bool) (value T, err error) { 65 if isCancel { 66 return 67 } 68 // func() (value T, hasValue bool) 69 var hasValue bool 70 if value, hasValue = i.iteratorFunction(); !hasValue { 71 err = cyclebreaker.ErrEndCallbacks 72 } 73 74 return 75 }