use crossbeam_queue::ArrayQueue;
use std::sync::Arc;
pub const MAX_DHT_UDP_PACKET: usize = 8192;
const INITIAL_POOL_SIZE: usize = 512;
const MAX_POOL_SIZE: usize = 4096;
pub struct UdpPacket {
pub buf: Box<[u8]>,
pub len: usize,
}
impl UdpPacket {
#[inline]
pub fn payload(&self) -> &[u8] {
&self.buf[..self.len]
}
}
#[derive(Clone)]
pub struct UdpBufferPool {
inner: Arc<PoolInner>,
}
struct PoolInner {
free: ArrayQueue<Box<[u8]>>,
buf_capacity: usize,
}
impl UdpBufferPool {
pub fn new() -> Self {
let free = ArrayQueue::new(MAX_POOL_SIZE);
for _ in 0..INITIAL_POOL_SIZE {
let _ = free.push(alloc_buffer(MAX_DHT_UDP_PACKET));
}
Self {
inner: Arc::new(PoolInner {
free,
buf_capacity: MAX_DHT_UDP_PACKET,
}),
}
}
pub fn acquire(&self) -> Box<[u8]> {
self.inner
.free
.pop()
.unwrap_or_else(|| alloc_buffer(self.inner.buf_capacity))
}
pub fn release(&self, buf: Box<[u8]>) {
if buf.len() != self.inner.buf_capacity {
return;
}
let _ = self.inner.free.push(buf);
}
pub fn buf_capacity(&self) -> usize {
self.inner.buf_capacity
}
}
fn alloc_buffer(capacity: usize) -> Box<[u8]> {
let v = vec![0; capacity];
v.into_boxed_slice()
}