1pub mod buf;
2
3use buf::Buf;
4use once_cell::sync::Lazy;
5use std::alloc::alloc;
6use std::alloc::Layout;
7use std::collections::VecDeque;
8use std::mem::size_of;
9use std::panic::RefUnwindSafe;
10use std::panic::UnwindSafe;
11use std::sync::Arc;
12
13#[derive(Clone, Default)]
15struct BufPoolForSize(Arc<parking_lot::Mutex<VecDeque<*mut u8>>>);
16
17unsafe impl Send for BufPoolForSize {}
18unsafe impl Sync for BufPoolForSize {}
19impl UnwindSafe for BufPoolForSize {}
20impl RefUnwindSafe for BufPoolForSize {}
21
22struct BufPoolInner {
23 align: usize,
24 #[cfg(not(feature = "no-pool"))]
25 sizes: Vec<BufPoolForSize>,
26}
27
28#[derive(Clone)]
29pub struct BufPool {
30 inner: Arc<BufPoolInner>,
31}
32
33impl BufPool {
34 pub fn with_alignment(align: usize) -> Self {
35 assert!(align > 0);
36 assert!(align.is_power_of_two());
37 Self {
38 inner: Arc::new(BufPoolInner {
39 align,
40 #[cfg(not(feature = "no-pool"))]
41 sizes: (0..(size_of::<usize>() * 8))
42 .map(|_| Default::default())
43 .collect(),
44 }),
45 }
46 }
47
48 pub fn new() -> Self {
49 Self::with_alignment(size_of::<usize>())
50 }
51
52 fn system_allocate_raw(&self, cap: usize) -> *mut u8 {
53 unsafe { alloc(Layout::from_size_align(cap, self.inner.align).unwrap()) }
54 }
55
56 pub fn allocate(&self, cap: usize) -> Buf {
59 let cap = cap.next_power_of_two();
61
62 #[cfg(not(feature = "no-pool"))]
63 let data = if let Some(data) = self.inner.sizes[cap.ilog2() as usize].0.lock().pop_front() {
64 data
65 } else {
66 self.system_allocate_raw(cap)
67 };
68 #[cfg(feature = "no-pool")]
69 let data = self.system_allocate_raw(cap);
70
71 assert!(!data.is_null());
73
74 Buf {
75 data,
76 len: 0,
77 cap,
78 pool: self.clone(),
79 }
80 }
81
82 pub fn allocate_from_data(&self, data: impl AsRef<[u8]>) -> Buf {
83 let mut buf = self.allocate(data.as_ref().len());
84 buf.extend_from_slice(data.as_ref());
85 buf
86 }
87
88 pub fn allocate_from_iter(&self, data: impl IntoIterator<Item = u8>, len: usize) -> Buf {
89 let mut buf = self.allocate(len);
90 buf.extend(data);
91 buf
92 }
93
94 pub fn allocate_uninitialised(&self, len: usize) -> Buf {
96 let mut buf = self.allocate(len);
97 unsafe { buf.set_len(len) };
98 buf
99 }
100
101 pub fn allocate_with_fill(&self, val: u8, len: usize) -> Buf {
102 let mut buf = self.allocate_uninitialised(len);
103 buf.fill(val);
104 buf
105 }
106
107 pub fn allocate_with_zeros(&self, len: usize) -> Buf {
108 self.allocate_with_fill(0, len)
109 }
110}
111
112pub static BUFPOOL: Lazy<BufPool> = Lazy::new(|| BufPool::new());