Skip to main content

bufferpool/
lib.rs

1//! Hey
2
3extern crate alloc;
4
5use alloc::rc::Rc;
6use core::cell::RefCell;
7use core::marker::PhantomData;
8
9type Used<V> = Rc<RefCell<Vec<V>>>;
10
11const BITS_IN_U32: usize = 32;
12
13fn value_of_index(values: &[u32], index: usize) -> Result<bool, ()> {
14    let value_index = index / BITS_IN_U32;
15    let offset = index % BITS_IN_U32;
16
17    if let Some(v) = values.get(value_index) {
18        if offset < 32 {
19            Ok(v & (1 << offset) != 0)
20        } else {
21            Err(())
22        }
23    } else {
24        Err(())
25    }
26}
27
28fn update_index(values: &mut [u32], index: usize, value: bool) -> Result<(), ()> {
29    let value_index = index / BITS_IN_U32;
30    let offset = index % BITS_IN_U32;
31
32    if let Some(v) = values.get_mut(value_index) {
33        if offset < 32 {
34            let mask = 1 << offset;
35            if value {
36                *v |= mask;
37            } else {
38                *v &= !mask;
39            }
40            Ok(())
41        } else {
42            Err(())
43        }
44    } else {
45        Err(())
46    }
47}
48
49/// A "vector of vectors" backed by a single contiguous vector.
50/// Allows for mutable borrows of non-overlapping regions.
51pub struct BufferPool<V: Default + Clone> {
52    buffer: Used<V>,
53    buffer_size: usize,
54    used: Used<u32>,
55}
56
57/// A builder interface for creating a new `BufferPool`.
58pub struct BufferPoolBuilder<V: Default + Clone> {
59    buffer_size: usize,
60    capacity: usize,
61    marker: PhantomData<V>,
62}
63
64impl<V: Clone + Default> Default for BufferPoolBuilder<V> {
65    fn default() -> BufferPoolBuilder<V> {
66        BufferPoolBuilder {
67            buffer_size: 1024,
68            capacity: 0,
69            marker: PhantomData {},
70        }
71    }
72}
73
74impl<V: Default + Clone> BufferPoolBuilder<V> {
75    pub fn new() -> BufferPoolBuilder<V> {
76        BufferPoolBuilder::default()
77    }
78
79    /// Set the capacity of the buffer pool - the max number of internal buffers.
80    pub fn with_capacity(mut self, capacity: usize) -> BufferPoolBuilder<V> {
81        self.capacity = capacity;
82        self
83    }
84
85    /// Set the buffer size / length of the internal buffers.
86    pub fn with_buffer_size(mut self, buffer_size: usize) -> BufferPoolBuilder<V> {
87        self.buffer_size = buffer_size;
88        self
89    }
90
91    pub fn build(self) -> BufferPool<V> {
92        BufferPool {
93            buffer_size: self.buffer_size,
94            buffer: Rc::new(RefCell::new(vec![
95                V::default();
96                self.capacity * self.buffer_size
97            ])),
98            used: Rc::new(RefCell::new(vec![
99                0;
100                if self.capacity == 0 {
101                    0
102                } else {
103                    1 + ((self.capacity - 1) / BITS_IN_U32)
104                }
105            ])),
106        }
107    }
108}
109
110impl<V: Default + Clone> Default for BufferPool<V> {
111    fn default() -> BufferPool<V> {
112        BufferPoolBuilder::default().build()
113    }
114}
115
116impl<V: Default + Clone> BufferPool<V> {
117    pub fn builder() -> BufferPoolBuilder<V> {
118        BufferPoolBuilder::default()
119    }
120
121    fn find_free_index(&self) -> Result<usize, ()> {
122        let mut index = 0;
123        let max_index = self.capacity();
124
125        loop {
126            let used = self.used.borrow();
127            let used = used.as_slice();
128
129            if index % BITS_IN_U32 == 0 {
130                if let Some(value) = used.get(index / BITS_IN_U32) {
131                    if value == &core::u32::MAX {
132                        index += BITS_IN_U32;
133                        continue;
134                    }
135                }
136            }
137
138            if let Ok(value) = value_of_index(used, index) {
139                if !value {
140                    return Ok(index);
141                } else {
142                    index += 1;
143
144                    if max_index <= index {
145                        return Err(());
146                    }
147                }
148            } else {
149                return Err(());
150            }
151        }
152    }
153
154    pub fn get_buffer_size(&self) -> usize {
155        self.buffer_size
156    }
157
158    /// Set all of the values back to their defaults
159    pub fn try_clear(&mut self) -> Result<(), ()> {
160        if self.is_borrowed() {
161            Err(())
162        } else {
163            let mut buffer = self.buffer.borrow_mut();
164            for value in buffer.as_mut_slice().iter_mut() {
165                *value = V::default();
166            }
167            Ok(())
168        }
169    }
170
171    /// Set all of the values back to their defaults
172    ///
173    /// # Panics
174    /// If any of the buffers have been borrowed.
175    pub fn clear(&mut self) {
176        if self.try_clear().is_err() {
177            panic!("Cannot clear when buffers are borrowed!");
178        }
179    }
180
181    fn set_index_used(&mut self, index: usize) -> Result<(), ()> {
182        let mut used = self.used.borrow_mut();
183        let used = used.as_mut_slice();
184        update_index(used, index, true)
185    }
186
187    fn find_free_index_and_use(&mut self) -> Result<usize, ()> {
188        if let Ok(index) = self.find_free_index() {
189            self.set_index_used(index).map(|_| index)
190        } else {
191            Err(())
192        }
193    }
194
195    /// Return the max number of buffers
196    pub fn capacity(&self) -> usize {
197        let mut buffer = self.buffer.borrow_mut();
198        buffer.as_mut_slice().len() / self.buffer_size
199    }
200
201    /// Resize the internal buffers
202    ///
203    /// # Panics
204    /// If any of the buffers have been borrowed.
205    pub fn change_buffer_size(&mut self, new_buffer_size: usize) {
206        if self.try_change_buffer_size(new_buffer_size).is_err() {
207            panic!("Cannot change buffer size when buffers are borrowed!");
208        }
209    }
210
211    /// Resize the internal buffers
212    pub fn try_change_buffer_size(&mut self, new_buffer_size: usize) -> Result<(), ()> {
213        let len = self.capacity();
214        self.buffer_size = new_buffer_size;
215        self.try_resize(len)
216    }
217
218    /// Resize both the capacity and buffers
219    ///
220    /// # Panics
221    /// If any of the buffers have been borrowed
222    pub fn resize_len_and_buffer(&mut self, new_len: usize, new_buffer_size: usize) {
223        self.buffer_size = new_buffer_size;
224        self.resize(new_len);
225    }
226
227    /// Check whether the buffer pool has no capacity
228    pub fn is_empty(&self) -> bool {
229        self.capacity() == 0
230    }
231    
232    /// Reserve an additional number of buffers
233    /// 
234    /// # Panics
235    /// If any of the buffers have been borrowed
236    pub fn reserve(&mut self, additional: usize) {
237        self.resize(self.capacity() + additional);
238    }
239
240    /// Reserve an additional number of buffers
241    pub fn try_reserve(&mut self, additional: usize) -> Result<(), ()> {
242        self.try_resize(self.capacity() + additional)
243    }
244
245    /// Checks to see whether any of the internal slices have been borrowed.
246    pub fn is_borrowed(&self) -> bool {
247        let mut index = 0;
248        let max_index = self.capacity();
249
250        let used = self.used.borrow();
251        let used = used.as_slice();
252
253        loop {
254            if let Ok(value) = value_of_index(used, index) {
255                if value {
256                    return false;
257                } else {
258                    index += 1;
259
260                    if max_index <= index {
261                        break;
262                    }
263                }
264            } else {
265                return false;
266            }
267        }
268
269        false
270    }
271
272    /// Change the number of internal buffers
273    ///
274    /// # Panics
275    /// If any of the internal buffers have been borrowed
276    pub fn resize(&mut self, new_len: usize) {
277        if self.try_resize(new_len).is_err() {
278            panic!("Can't resize when borrowed!");
279        }
280    }
281
282    /// Change the number of internal buffers
283    pub fn try_resize(&mut self, new_len: usize) -> Result<(), ()> {
284        if self.is_borrowed() {
285            Err(())
286        } else {
287            let mut buffer = self.buffer.borrow_mut();
288            (*buffer).resize_with(new_len * self.buffer_size, V::default);
289
290            let mut used_capacity = self.used.borrow().len() * BITS_IN_U32;
291
292            while used_capacity < new_len {
293                let new_len = self.used.borrow().len() + 1;
294
295                self.used.borrow_mut().resize(new_len, 0);
296
297                used_capacity = self.used.borrow().len() * BITS_IN_U32;
298            }
299
300            Ok(())
301        }
302    }
303
304    /// Get a reference to a slice of the `BufferPool` setting the values of the
305    /// pool back to their default value.
306    pub fn get_cleared_space(&mut self) -> Result<BufferPoolReference<V>, ()> {
307        self.get_space().and_then(|mut space| {
308            for value in space.as_mut().iter_mut() {
309                *value = V::default();
310            }
311
312            Ok(space)
313        })
314    }
315
316    /// Get a reference to a slice of the `BufferPool`.
317    pub fn get_space(&mut self) -> Result<BufferPoolReference<V>, ()> {
318        self.find_free_index_and_use().and_then(|index| {
319            let slice = unsafe {
320                (*self.buffer.borrow_mut())
321                    .as_mut_ptr()
322                    .add(index * self.buffer_size)
323            };
324
325            Ok(BufferPoolReference {
326                index,
327                used: Rc::clone(&self.used),
328                parent: Rc::clone(&self.buffer),
329                buffer_size: self.buffer_size,
330                slice,
331            })
332        })
333    }
334}
335
336/// A reference to a slice of the `BufferPool`.
337/// When dropped it will finish the borrow and return
338/// the space.
339pub struct BufferPoolReference<V> {
340    index: usize,
341    used: Used<u32>,
342    // This is only here so it will stay around
343    // after the parent is deallocated - never use
344    // it!
345    #[allow(dead_code)]
346    parent: Used<V>,
347    slice: *mut V,
348    buffer_size: usize,
349}
350
351impl<V> AsMut<[V]> for BufferPoolReference<V> {
352    fn as_mut(&mut self) -> &mut [V] {
353        unsafe { alloc::slice::from_raw_parts_mut(self.slice, self.buffer_size) }
354    }
355}
356
357impl<V> AsRef<[V]> for BufferPoolReference<V> {
358    fn as_ref(&self) -> &[V] {
359        unsafe { alloc::slice::from_raw_parts(self.slice, self.buffer_size) }
360    }
361}
362
363impl<V> Drop for BufferPoolReference<V> {
364    fn drop(&mut self) {
365        let mut used = self.used.borrow_mut();
366        let used = used.as_mut_slice();
367
368        if update_index(used, self.index, false).is_err() {
369            panic!("Unable to free reference for index {}!", self.index);
370        }
371    }
372}
373
374#[cfg(test)]
375mod tests {
376    use super::*;
377
378    #[test]
379    fn it_should_add_capacity() {
380        let mut pool: BufferPool<f32> = BufferPool::default();
381
382        assert_eq!(pool.capacity(), 0);
383
384        pool.reserve(1);
385
386        assert_eq!(pool.capacity(), 1);
387
388        pool.reserve(1);
389
390        assert_eq!(pool.capacity(), 2);
391    }
392
393    #[test]
394    fn it_should_get_space_if_capacity() {
395        let mut pool: BufferPool<f32> = BufferPool::default();
396
397        assert_eq!(pool.capacity(), 0);
398
399        assert!(pool.get_space().is_err());
400
401        pool.resize(1);
402
403        let index = pool.get_space().unwrap();
404
405        assert!(pool.get_space().is_err());
406        assert_eq!(index.index, 0);
407    }
408
409    #[test]
410    fn it_should_work_with_interesting_sizes() {
411        let sizes: Vec<usize> = vec![12, 100, 1001, 1024, 2048, 4096, 1];
412
413        for buffer_size in sizes.iter() {
414            for capacity in sizes.iter() {
415                let mut pool: BufferPool<f32> = BufferPoolBuilder::new()
416                    .with_buffer_size(*buffer_size)
417                    .with_capacity(*capacity)
418                    .build();
419
420                assert_eq!(pool.capacity(), *capacity);
421                assert_eq!(pool.get_space().is_err(), false);
422            }
423        }
424    }
425
426    #[test]
427    fn it_should_return_space_when_deallocated() {
428        let mut pool: BufferPool<f32> = BufferPool::default();
429
430        assert_eq!(pool.capacity(), 0);
431        pool.reserve(1);
432
433        {
434            let index = pool.get_space().unwrap();
435            assert!(pool.get_space().is_err());
436            assert_eq!(index.index, 0);
437        }
438
439        assert!(pool.get_space().is_ok());
440    }
441
442    #[test]
443    fn it_should_update_internal_buffer() {
444        let buffer_size = 10;
445        let mut pool: BufferPool<f32> = BufferPool::default();
446        pool.change_buffer_size(buffer_size);
447        pool.reserve(10);
448
449        let mut a = pool.get_space().unwrap();
450        let mut b = pool.get_space().unwrap();
451
452        for value in a.as_mut().iter_mut() {
453            *value = 1.;
454        }
455
456        for value in b.as_mut().iter_mut() {
457            *value = 2.;
458        }
459
460        let buffer = pool.buffer.borrow();
461        assert_eq!(
462            (*buffer)[0..(buffer_size)],
463            vec![1. as f32; buffer_size][..]
464        );
465
466        assert_eq!(*a.as_ref(), vec![1. as f32; buffer_size][..]);
467
468        let buffer = pool.buffer.borrow();
469        assert_eq!(
470            (*buffer)[(buffer_size)..(2 * buffer_size)],
471            vec![2. as f32; buffer_size][..]
472        );
473
474        assert_eq!(*b.as_ref(), vec![2. as f32; buffer_size][..]);
475    }
476
477    #[test]
478    fn it_should_not_default_space_when_deallocated() {
479        let buffer_size = 10;
480        let mut pool: BufferPool<f32> = BufferPool::default();
481        pool.change_buffer_size(buffer_size);
482        pool.reserve(10);
483
484        {
485            let mut a = pool.get_space().unwrap();
486
487            for value in a.as_mut().iter_mut() {
488                *value = 1.;
489            }
490
491            let buffer = pool.buffer.borrow();
492            assert_eq!(
493                (*buffer)[0..(buffer_size)],
494                vec![1. as f32; buffer_size][..]
495            );
496
497            assert_eq!(*a.as_ref(), vec![1. as f32; buffer_size][..]);
498        }
499
500        let buffer = pool.buffer.borrow();
501
502        assert_eq!(
503            (*buffer)[0..(buffer_size)],
504            vec![1. as f32; buffer_size][..]
505        );
506    }
507
508    #[test]
509    fn it_should_clear_space_if_explicitly_requested() {
510        let buffer_size = 10;
511        let mut pool: BufferPool<f32> = BufferPool::default();
512        pool.change_buffer_size(buffer_size);
513        pool.reserve(10);
514
515        {
516            let mut a = pool.get_space().unwrap();
517
518            for value in a.as_mut().iter_mut() {
519                *value = 1.;
520            }
521
522            let buffer = pool.buffer.borrow();
523
524            assert_eq!(
525                (*buffer)[0..(buffer_size)],
526                vec![1. as f32; buffer_size][..]
527            );
528
529            assert_eq!(*a.as_ref(), vec![1. as f32; buffer_size][..]);
530        }
531
532        let space = pool.get_cleared_space().unwrap();
533
534        let buffer = pool.buffer.borrow();
535
536        assert_eq!(
537            (*buffer)[0..(buffer_size)],
538            vec![0. as f32; buffer_size][..]
539        );
540
541        assert_eq!(*space.as_ref(), vec![0. as f32; buffer_size][..]);
542    }
543
544    #[test]
545    fn it_should_still_work_if_parent_is_dropped() {
546        let buffer_size = 10;
547        let mut pool: BufferPool<usize> = BufferPool::default();
548        pool.change_buffer_size(buffer_size);
549        pool.reserve(10);
550
551        let space = pool.get_cleared_space().unwrap();
552
553        drop(pool);
554
555        let value = space.as_ref().iter().fold(0, |a, b| a + b);
556        assert_eq!(value, 0);
557    }
558}