Skip to content

Commit

Permalink
Feat[pool]: IsClosed() function
Browse files Browse the repository at this point in the history
  • Loading branch information
yunginnanet committed May 25, 2023
1 parent 22a512b commit 85943b8
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
26 changes: 22 additions & 4 deletions pool/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,16 @@ func (cf BufferFactory) Get() *Buffer {
// Buffer is a wrapper around bytes.Buffer that can only be returned to a pool once.
type Buffer struct {
*bytes.Buffer
o *sync.Once
p *BufferFactory
o *sync.Once
co *sync.Once
p *BufferFactory
}

// WithParent sets the parent of the buffer. This is useful for chaining factories, and for facilitating
// in-line buffer return with functions like Buffer.Close(). Be mindful, however, that this adds a bit of overhead.
func (c Buffer) WithParent(p *BufferFactory) *Buffer {
c.p = p
c.co = &sync.Once{}
return &c
}

Expand Down Expand Up @@ -423,15 +425,31 @@ func (c Buffer) Next(n int) []byte {
return c.Buffer.Next(n)
}

// IsClosed returns true if the buffer has been returned to the pool.
func (c Buffer) IsClosed() bool {
var closed = true
if c.co == nil {
c.co = &sync.Once{}
}
c.co.Do(func() {
closed = false
})
return closed
}

// Close implements io.Closer. It returns the buffer to the pool. This
func (c Buffer) Close() error {
if c.Buffer == nil {
return errors.New("buffer already returned to pool")
}
if c.p == nil {
return errors.New(
"buffer does not know it's parent pool and therefore cannot return itself, use Buffer.WithParent to set the parent pool",
"buffer does not know it's parent pool and therefore cannot return itself, use Buffer.WithParent",
)
}
return c.p.Put(&c)
var err = ErrBufferReturned
c.co.Do(func() {
err = c.p.Put(&c)
})
return err
}
12 changes: 12 additions & 0 deletions pool/bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,16 +532,28 @@ func TestBufferFactory(t *testing.T) {
buf.MustWrite([]byte("hello"))
buf.MustWrite([]byte("world"))
buf.MustWrite([]byte("!"))
if buf.IsClosed() {
t.Fatalf("The buffer is closed before closing")
}
if err := buf.Close(); err == nil {
t.Fatal("The error is nil after closing the buffer with no parent")
}
if buf.IsClosed() {
t.Fatalf("The buffer is closed after failing to close")
}
if buf.String() != "helloworld!" {
t.Fatalf("The string is not 'helloworld!' after unsuccessful close: %v", buf.String())
}
buf = buf.WithParent(&bf)
if err := buf.Close(); err != nil {
t.Fatal(err)
}
if !buf.IsClosed() {
t.Fatalf("The buffer is not closed after closing")
}
if err := buf.Close(); err == nil {
t.Fatal("The error is nil after closing an already closed buffer")
}
})
t.Run("BufferCannotClose", func(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit 85943b8

Please sign in to comment.