Commit 4fd7013e authored by Matthew Sykes's avatar Matthew Sykes Committed by Gari Singh
Browse files

[FAB-13347] introduce counting semaphore



The counting semaphore will be used as part of throttling
implementation.

Change-Id: Ie8741414a6b25373072a611a55620519051489cc
Signed-off-by: default avatarMatthew Sykes <sykesmat@us.ibm.com>
(cherry picked from commit f975549503d76c276adfad52c1061901526bb410)
parent b43fcc77
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package semaphore
import "context"
type Semaphore chan struct{}
func New(count int) Semaphore {
if count <= 0 {
panic("count must be greater than 0")
}
return make(chan struct{}, count)
}
func (s Semaphore) Acquire(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case s <- struct{}{}:
return nil
}
}
func (s Semaphore) Release() {
select {
case <-s:
default:
panic("semaphore buffer is empty")
}
}
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package semaphore_test
import (
"context"
"testing"
"github.com/hyperledger/fabric/common/semaphore"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
)
func TestNewSemaphorePanic(t *testing.T) {
assert.PanicsWithValue(t, "count must be greater than 0", func() { semaphore.New(0) })
}
func TestSemaphoreBlocking(t *testing.T) {
gt := NewGomegaWithT(t)
sema := semaphore.New(5)
for i := 0; i < 5; i++ {
err := sema.Acquire(context.Background())
gt.Expect(err).NotTo(HaveOccurred())
}
done := make(chan struct{})
go func() {
err := sema.Acquire(context.Background())
gt.Expect(err).NotTo(HaveOccurred())
close(done)
sema.Release()
}()
gt.Consistently(done).ShouldNot(BeClosed())
sema.Release()
gt.Eventually(done).Should(BeClosed())
}
func TestSemaphoreContextError(t *testing.T) {
gt := NewGomegaWithT(t)
sema := semaphore.New(1)
err := sema.Acquire(context.Background())
gt.Expect(err).NotTo(HaveOccurred())
ctx, cancel := context.WithCancel(context.Background())
cancel()
errCh := make(chan error, 1)
go func() { errCh <- sema.Acquire(ctx) }()
gt.Eventually(errCh).Should(Receive(Equal(context.Canceled)))
}
func TestSemaphoreReleaseTooMany(t *testing.T) {
sema := semaphore.New(1)
assert.PanicsWithValue(t, "semaphore buffer is empty", func() { sema.Release() })
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment