wireguard-go/device/pools.go

117 lines
2.8 KiB
Go
Raw Normal View History

2019-01-02 01:55:51 +01:00
/* SPDX-License-Identifier: MIT
2018-09-22 06:29:02 +02:00
*
* Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
2018-09-22 06:29:02 +02:00
*/
2019-03-03 04:04:41 +01:00
package device
2018-09-22 06:29:02 +02:00
import (
"sync"
"sync/atomic"
)
2018-09-22 06:29:02 +02:00
type WaitPool struct {
pool sync.Pool
cond sync.Cond
lock sync.Mutex
count atomic.Uint32
max uint32
}
func NewWaitPool(max uint32, new func() any) *WaitPool {
p := &WaitPool{pool: sync.Pool{New: new}, max: max}
p.cond = sync.Cond{L: &p.lock}
return p
}
func (p *WaitPool) Get() any {
if p.max != 0 {
p.lock.Lock()
for p.count.Load() >= p.max {
p.cond.Wait()
2018-09-22 06:29:02 +02:00
}
p.count.Add(1)
p.lock.Unlock()
2018-09-22 06:29:02 +02:00
}
return p.pool.Get()
2018-09-22 06:29:02 +02:00
}
func (p *WaitPool) Put(x any) {
p.pool.Put(x)
if p.max == 0 {
return
2018-09-22 06:29:02 +02:00
}
p.count.Add(^uint32(0))
p.cond.Signal()
}
func (device *Device) PopulatePools() {
device.pool.outboundElementsSlice = NewWaitPool(PreallocatedBuffersPerPool, func() any {
s := make([]*QueueOutboundElement, 0, device.BatchSize())
return &s
})
device.pool.inboundElementsSlice = NewWaitPool(PreallocatedBuffersPerPool, func() any {
s := make([]*QueueInboundElement, 0, device.BatchSize())
return &s
})
device.pool.messageBuffers = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new([MaxMessageSize]byte)
})
device.pool.inboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new(QueueInboundElement)
})
device.pool.outboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new(QueueOutboundElement)
})
}
func (device *Device) GetOutboundElementsSlice() *[]*QueueOutboundElement {
return device.pool.outboundElementsSlice.Get().(*[]*QueueOutboundElement)
}
func (device *Device) PutOutboundElementsSlice(s *[]*QueueOutboundElement) {
for i := range *s {
(*s)[i] = nil
}
*s = (*s)[:0]
device.pool.outboundElementsSlice.Put(s)
}
func (device *Device) GetInboundElementsSlice() *[]*QueueInboundElement {
return device.pool.inboundElementsSlice.Get().(*[]*QueueInboundElement)
}
func (device *Device) PutInboundElementsSlice(s *[]*QueueInboundElement) {
for i := range *s {
(*s)[i] = nil
}
*s = (*s)[:0]
device.pool.inboundElementsSlice.Put(s)
}
func (device *Device) GetMessageBuffer() *[MaxMessageSize]byte {
return device.pool.messageBuffers.Get().(*[MaxMessageSize]byte)
2018-09-22 06:29:02 +02:00
}
func (device *Device) PutMessageBuffer(msg *[MaxMessageSize]byte) {
device.pool.messageBuffers.Put(msg)
2018-09-22 06:29:02 +02:00
}
func (device *Device) GetInboundElement() *QueueInboundElement {
return device.pool.inboundElements.Get().(*QueueInboundElement)
2018-09-22 06:29:02 +02:00
}
func (device *Device) PutInboundElement(elem *QueueInboundElement) {
elem.clearPointers()
device.pool.inboundElements.Put(elem)
2018-09-22 06:29:02 +02:00
}
func (device *Device) GetOutboundElement() *QueueOutboundElement {
return device.pool.outboundElements.Get().(*QueueOutboundElement)
2018-09-22 06:29:02 +02:00
}
func (device *Device) PutOutboundElement(elem *QueueOutboundElement) {
elem.clearPointers()
device.pool.outboundElements.Put(elem)
2018-09-22 06:29:02 +02:00
}