github.com/haraldrudell/parl@v0.4.176/pio/close-callbacker.go (about)

     1  /*
     2  © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pio
     7  
     8  import (
     9  	"io"
    10  
    11  	"github.com/haraldrudell/parl"
    12  	"github.com/haraldrudell/parl/perrors"
    13  )
    14  
    15  // Go does not allow promotion of a type parameter
    16  // https://github.com/golang/go/issues/49030
    17  // interfaces:
    18  var _ io.ReadCloser
    19  var _ io.ReadSeekCloser
    20  var _ io.ReadWriteCloser
    21  var _ io.WriteCloser
    22  var _ io.Closer
    23  
    24  type CloseCallback func(err error) (e error)
    25  
    26  // CloseCallbacker implements a close callback for io.Closer
    27  // 231128 unused
    28  type CloseCallbacker struct {
    29  	closer        io.Closer
    30  	closeCallback CloseCallback
    31  	isClosed      parl.Awaitable
    32  }
    33  
    34  var _ io.Closer = &CloseCallbacker{}
    35  
    36  func NewCloseCallbacker(closer io.Closer, closeCallback CloseCallback) (closeCallbacker *CloseCallbacker) {
    37  	if closer == nil {
    38  		panic(parl.NilError("closer"))
    39  	} else if closeCallback == nil {
    40  		panic(parl.NilError("closeCallback"))
    41  	}
    42  	return &CloseCallbacker{
    43  		closer:        closer,
    44  		closeCallback: closeCallback,
    45  	}
    46  }
    47  
    48  func (c *CloseCallbacker) Close() (err error) {
    49  	if !c.isClosed.Close() {
    50  		return // already closed
    51  	}
    52  	parl.Close(c.closer, &err)
    53  	var e = c.invokeCloseCallback(err)
    54  	if e != nil && e != err {
    55  		err = perrors.AppendError(err, e)
    56  	}
    57  	return
    58  }
    59  
    60  func (c *CloseCallbacker) IsClosed() (isClosed bool) { return c.isClosed.IsClosed() }
    61  
    62  func (c *CloseCallbacker) Wait() { <-c.isClosed.Ch() }
    63  
    64  func (c *CloseCallbacker) invokeCloseCallback(e error) (err error) {
    65  	defer parl.RecoverErr(func() parl.DA { return parl.A() }, &err)
    66  
    67  	err = c.closeCallback(e)
    68  
    69  	return
    70  }