frostfs-qos/limiting/semaphore.go
Aleksey Savchuk b52a5e1d2d
[#4] limiting: Add different implementation of semaphore
Added different implementations of a semaphore used in the limiter.
They'll be compared to choose one with best perfomance, then may
drop others in the future.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2025-02-13 11:27:16 +03:00

74 lines
1.2 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)
}
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
}