github.com/git-amp/amp-sdk-go@v0.7.5/stdlib/generics/ref-closer.go (about) 1 package generics 2 3 import ( 4 "io" 5 "sync/atomic" 6 ) 7 8 // RefCloser is a reference counted io.Closer where the wrapped Closer is closed when its reference count reaches zero. 9 type RefCloser interface { 10 11 // AddRef atomically increments the reference count. 12 AddRef() 13 14 // Release atomically decrements the reference count. 15 // If the ref count is remains greater than zero, nil is returned. 16 // If the ref count reaches zero, the underlying Closer was closed and it's error is returned. 17 Close() error 18 } 19 20 // Wraps the given io.Closer into a RefCloser, initializing its reference count to 1. 21 func WrapInRefCloser(target io.Closer) RefCloser { 22 rc := &refCloser{ 23 closer: target, 24 refCount: 1, 25 } 26 return rc 27 } 28 29 type refCloser struct { 30 closer io.Closer 31 refCount int32 32 } 33 34 func (rc *refCloser) AddRef() { 35 atomic.AddInt32(&rc.refCount, 1) 36 } 37 38 func (rc *refCloser) Close() error { 39 if atomic.AddInt32(&rc.refCount, -1) > 0 { 40 return nil 41 } 42 err := rc.closer.Close() 43 rc.closer = nil 44 return err 45 }