comet/allocator/
overflow.rs

1use crate::{
2    block::Block,
3    block_allocator::BlockAllocator,
4    globals::{IMMIX_BLOCK_SIZE, LINE_SIZE},
5    internal::{block_list::BlockList, space_bitmap::SpaceBitmap},
6};
7
8use super::{Allocator, BlockTuple};
9
10/// The `OverflowAllocator` is used to allocate *medium* sized objects
11/// (objects of at least `MEDIUM_OBJECT` bytes size) within the immix space to
12/// limit fragmentation in the `NormalAllocator`.
13pub struct OverflowAllocator {
14    /// The global `BlockAllocator` to get new blocks from.
15    pub(crate) block_allocator: *mut BlockAllocator,
16    pub(crate) line_bitmap: *const SpaceBitmap<LINE_SIZE>,
17    /// The exhausted blocks.
18    unavailable_blocks: BlockList,
19
20    /// The current block to allocate from.
21    current_block: Option<BlockTuple>,
22}
23
24impl OverflowAllocator {
25    /// Create a new `OverflowAllocator` backed by the given `BlockAllocator`.
26    pub fn new(
27        block_allocator: *mut BlockAllocator,
28        bitmap: *const SpaceBitmap<LINE_SIZE>,
29    ) -> OverflowAllocator {
30        OverflowAllocator {
31            block_allocator: block_allocator,
32            unavailable_blocks: BlockList::new(),
33            line_bitmap: unsafe { &*bitmap },
34            current_block: None,
35        }
36    }
37}
38
39impl Allocator for OverflowAllocator {
40    fn line_bitmap(&self) -> &SpaceBitmap<LINE_SIZE> {
41        unsafe { &*self.line_bitmap }
42    }
43    fn get_all_blocks(&mut self, list: &mut BlockList) {
44        while !self.unavailable_blocks.is_empty() {
45            list.push(self.unavailable_blocks.pop());
46        }
47        self.current_block.take().iter().for_each(|block| {
48            list.push(block.0);
49        });
50        /*self.unavailable_blocks
51        .drain(..)
52        .chain(self.current_block.take().map(|b| b.0))
53        .collect()*/
54    }
55
56    fn take_current_block(&mut self) -> Option<BlockTuple> {
57        self.current_block.take()
58    }
59
60    fn put_current_block(&mut self, block_tuple: BlockTuple) {
61        self.current_block = Some(block_tuple);
62    }
63
64    fn get_new_block(&mut self) -> Option<BlockTuple> {
65        /*self.block_allocator
66        .borrow_mut()
67        .get_block()
68        .map(|b| unsafe {
69            (*b).set_allocated();
70            b
71        })
72        .map(|block| (block, LINE_SIZE as u16, (BLOCK_SIZE - 1) as u16))*/
73        unsafe {
74            let block = (*self.block_allocator).get_block();
75            if block.is_null() {
76                return None;
77            }
78            (*block).set_allocated();
79            Some((block, LINE_SIZE as _, IMMIX_BLOCK_SIZE as u16 - 1))
80        }
81    }
82
83    #[allow(unused_variables)]
84    fn handle_no_hole(&mut self, size: usize) -> Option<BlockTuple> {
85        None
86    }
87
88    fn handle_full_block(&mut self, block: *mut Block) {
89        self.unavailable_blocks.push(block);
90    }
91}