frostfs-qos/limiting/semaphore.go
Aleksey Savchuk a37e3dc381
All checks were successful
DCO action / DCO (pull_request) Successful in 32s
Vulncheck / Vulncheck (pull_request) Successful in 40s
Tests and linters / Run gofumpt (pull_request) Successful in 39s
Tests and linters / Staticcheck (pull_request) Successful in 1m2s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m22s
Tests and linters / Lint (pull_request) Successful in 1m27s
Tests and linters / Tests (pull_request) Successful in 1m29s
Tests and linters / Tests with -race (pull_request) Successful in 1m31s
Tests and linters / gopls check (pull_request) Successful in 1m38s
[#4] limiting: Add benchmarks
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2025-02-13 10:29:44 +03:00

87 lines
1.5 KiB
Go

package limiting
import (
"sync/atomic"
)
type atomicSemaphore struct {
countDown atomic.Int64
}
func newAtomicSemaphore(size int64) *atomicSemaphore {
sem := new(atomicSemaphore)
sem.countDown.Store(size)
return sem
}
func (s *atomicSemaphore) acquire() bool {
for {
v := s.countDown.Load()
if v == 0 {
return false
}
if s.countDown.CompareAndSwap(v, v-1) {
return true
}
}
}
func (s *atomicSemaphore) release() {
s.countDown.Add(1)
}
type burstAtomicSemaphore struct {
count atomic.Int64
limit int64
}
func newBurstAtomicSemaphore(size int64) *burstAtomicSemaphore {
return &burstAtomicSemaphore{limit: size}
}
func (s *burstAtomicSemaphore) acquire() bool {
v := s.count.Add(1)
if v > s.limit {
s.count.Add(-1)
return false
}
return true
}
func (s *burstAtomicSemaphore) release() {
s.count.Add(-1)
}
// acquireWithReturnLimit calls [acquire] and returns current limit if failed.
// This is used for test purposes only.
//
//nolint:unused
func (s *burstAtomicSemaphore) acquireWithReturnLimit() (bool, int64) {
v := s.count.Add(1)
if v > s.limit {
s.count.Add(-1)
return false, v - 1
}
return true, v
}
type channelSemaphore struct {
ch chan struct{}
}
func newChannelSemaphore(size int64) *channelSemaphore {
return &channelSemaphore{make(chan struct{}, size)}
}
func (s *channelSemaphore) acquire() bool {
select {
case s.ch <- struct{}{}:
return true
default:
return false
}
}
func (s *channelSemaphore) release() {
<-s.ch
}