Browse Source

sync: move closer to separate file (#6015)

Closes: #6013
pull/6022/head
Aleksandr Bezobchuk 4 years ago
committed by GitHub
parent
commit
17905cbaa2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 56 deletions
  1. +31
    -0
      libs/sync/closer.go
  2. +28
    -0
      libs/sync/closer_test.go
  3. +0
    -28
      libs/sync/deadlock.go
  4. +0
    -28
      libs/sync/sync.go

+ 31
- 0
libs/sync/closer.go View File

@ -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)
})
}

+ 28
- 0
libs/sync/closer_test.go View File

@ -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()
}

+ 0
- 28
libs/sync/deadlock.go View File

@ -15,31 +15,3 @@ type Mutex struct {
type RWMutex struct { type RWMutex struct {
deadlock.RWMutex 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)
})
}

+ 0
- 28
libs/sync/sync.go View File

@ -13,31 +13,3 @@ type Mutex struct {
type RWMutex struct { type RWMutex struct {
sync.RWMutex 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)
})
}

Loading…
Cancel
Save