mirror of
https://github.com/foxcpp/maddy.git
synced 2025-04-05 14:07:38 +03:00
Set of flow restrictions is represented as a "limits" module instance that can be either created inline via "limits" directive in some modules (including "remote" target and "smtp" endpoint) or defined globally and referenced in configuration of modules mentioned above. This permits a variety of use cases, including shared and separate counters for various endpoints and also "modules group" style sharing described in #195.
50 lines
839 B
Go
50 lines
839 B
Go
package limiters
|
|
|
|
import "context"
|
|
|
|
// Semaphore is a convenience wrapper for a channel that implements
|
|
// semaphore-kind synchronization.
|
|
//
|
|
// If the argument given to the NewSemaphore is negative or zero,
|
|
// all methods are no-op.
|
|
type Semaphore struct {
|
|
c chan struct{}
|
|
}
|
|
|
|
func NewSemaphore(max int) Semaphore {
|
|
return Semaphore{c: make(chan struct{}, max)}
|
|
}
|
|
|
|
func (s Semaphore) Take() bool {
|
|
if cap(s.c) <= 0 {
|
|
return true
|
|
}
|
|
s.c <- struct{}{}
|
|
return true
|
|
}
|
|
|
|
func (s Semaphore) TakeContext(ctx context.Context) error {
|
|
if cap(s.c) <= 0 {
|
|
return nil
|
|
}
|
|
select {
|
|
case s.c <- struct{}{}:
|
|
return nil
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
}
|
|
}
|
|
|
|
func (s Semaphore) Release() {
|
|
if cap(s.c) <= 0 {
|
|
return
|
|
}
|
|
select {
|
|
case <-s.c:
|
|
default:
|
|
panic("limiters: mismatched Release call")
|
|
}
|
|
}
|
|
|
|
func (s Semaphore) Close() {
|
|
}
|