From 17905cbaa233872f947f16551798069af7316432 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Fri, 29 Jan 2021 11:59:15 -0500 Subject: [PATCH] sync: move closer to separate file (#6015) Closes: #6013 --- libs/sync/closer.go | 31 +++++++++++++++++++++++++++++++ libs/sync/closer_test.go | 28 ++++++++++++++++++++++++++++ libs/sync/deadlock.go | 28 ---------------------------- libs/sync/sync.go | 28 ---------------------------- 4 files changed, 59 insertions(+), 56 deletions(-) create mode 100644 libs/sync/closer.go create mode 100644 libs/sync/closer_test.go diff --git a/libs/sync/closer.go b/libs/sync/closer.go new file mode 100644 index 000000000..815ee1e80 --- /dev/null +++ b/libs/sync/closer.go @@ -0,0 +1,31 @@ +package sync + +import "sync" + +// Closer implements a primitive to close a channel that signals process +// termination while allowing a caller to call Close multiple times safely. It +// should be used in cases where guarantees cannot be made about when and how +// many times closure is executed. +type Closer struct { + closeOnce sync.Once + doneCh chan struct{} +} + +// NewCloser returns a reference to a new Closer. +func NewCloser() *Closer { + return &Closer{doneCh: make(chan struct{})} +} + +// Done returns the internal done channel allowing the caller either block or wait +// for the Closer to be terminated/closed. +func (c *Closer) Done() <-chan struct{} { + return c.doneCh +} + +// Close gracefully closes the Closer. A caller should only call Close once, but +// it is safe to call it successive times. +func (c *Closer) Close() { + c.closeOnce.Do(func() { + close(c.doneCh) + }) +} diff --git a/libs/sync/closer_test.go b/libs/sync/closer_test.go new file mode 100644 index 000000000..40f7a12e3 --- /dev/null +++ b/libs/sync/closer_test.go @@ -0,0 +1,28 @@ +package sync_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + tmsync "github.com/tendermint/tendermint/libs/sync" +) + +func TestCloser(t *testing.T) { + closer := tmsync.NewCloser() + + var timeout bool + + select { + case <-closer.Done(): + case <-time.After(time.Second): + timeout = true + } + + for i := 0; i < 10; i++ { + closer.Close() + } + + require.True(t, timeout) + <-closer.Done() +} diff --git a/libs/sync/deadlock.go b/libs/sync/deadlock.go index 38627b7cb..637d6fbb1 100644 --- a/libs/sync/deadlock.go +++ b/libs/sync/deadlock.go @@ -15,31 +15,3 @@ type Mutex struct { type RWMutex struct { deadlock.RWMutex } - -// Closer implements a primitive to close a channel that signals process -// termination while allowing a caller to call Close multiple times safely. It -// should be used in cases where guarantees cannot be made about when and how -// many times closure is executed. -type Closer struct { - closeOnce deadlock.Once - doneCh chan struct{} -} - -// NewCloser returns a reference to a new Closer. -func NewCloser() *Closer { - return &Closer{doneCh: make(chan struct{})} -} - -// Done returns the internal done channel allowing the caller either block or wait -// for the Closer to be terminated/closed. -func (c *Closer) Done() <-chan struct{} { - return c.doneCh -} - -// Close gracefully closes the Closer. A caller should only call Close once, but -// it is safe to call it successive times. -func (c *Closer) Close() { - c.closeOnce.Do(func() { - close(c.doneCh) - }) -} diff --git a/libs/sync/sync.go b/libs/sync/sync.go index 32fe29e53..a0880e7de 100644 --- a/libs/sync/sync.go +++ b/libs/sync/sync.go @@ -13,31 +13,3 @@ type Mutex struct { type RWMutex struct { sync.RWMutex } - -// Closer implements a primitive to close a channel that signals process -// termination while allowing a caller to call Close multiple times safely. It -// should be used in cases where guarantees cannot be made about when and how -// many times closure is executed. -type Closer struct { - closeOnce sync.Once - doneCh chan struct{} -} - -// NewCloser returns a reference to a new Closer. -func NewCloser() *Closer { - return &Closer{doneCh: make(chan struct{})} -} - -// Done returns the internal done channel allowing the caller either block or wait -// for the Closer to be terminated/closed. -func (c *Closer) Done() <-chan struct{} { - return c.doneCh -} - -// Close gracefully closes the Closer. A caller should only call Close once, but -// it is safe to call it successive times. -func (c *Closer) Close() { - c.closeOnce.Do(func() { - close(c.doneCh) - }) -}