comet/allocator/
normal.rs1use 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
10pub struct NormalAllocator {
15 pub(crate) block_allocator: *mut BlockAllocator,
17
18 unavailable_blocks: BlockList,
20
21 pub(crate) recyclable_blocks: BlockList,
23
24 current_block: Option<BlockTuple>,
26 pub(crate) line_bitmap: *const SpaceBitmap<LINE_SIZE>,
27}
28impl NormalAllocator {
29 pub fn new(
31 block_allocator: *mut BlockAllocator,
32 bitmap: *const SpaceBitmap<LINE_SIZE>,
33 ) -> NormalAllocator {
34 NormalAllocator {
35 block_allocator: block_allocator,
36 unavailable_blocks: BlockList::new(),
37 recyclable_blocks: BlockList::new(),
38 current_block: None,
39 line_bitmap: bitmap,
40 }
41 }
42
43 pub fn set_recyclable_blocks(&mut self, blocks: BlockList) {
45 self.recyclable_blocks = blocks;
46 }
47}
48
49impl Allocator for NormalAllocator {
50 fn get_all_blocks(&mut self, list: &mut BlockList) {
51 while !self.unavailable_blocks.is_empty() {
52 list.push(self.unavailable_blocks.pop());
53 }
54 while !self.recyclable_blocks.is_empty() {
55 list.push(self.recyclable_blocks.pop());
56 }
57 if let Some(block) = self.current_block.take() {
58 list.push((block).0);
59 }
60 }
61
62 fn take_current_block(&mut self) -> Option<BlockTuple> {
63 self.current_block.take()
64 }
65
66 fn put_current_block(&mut self, block_tuple: BlockTuple) {
67 self.current_block = Some(block_tuple);
68 }
69
70 fn get_new_block(&mut self) -> Option<BlockTuple> {
71 unsafe {
72 let block = (*self.block_allocator).get_block();
73 if block.is_null() {
74 return None;
75 }
76 (*block).set_allocated();
77
78 Some((block, LINE_SIZE as u16, IMMIX_BLOCK_SIZE as u16 - 1))
79 }
80 }
81 fn line_bitmap(&self) -> &SpaceBitmap<LINE_SIZE> {
82 unsafe { &*self.line_bitmap }
83 }
84 fn handle_no_hole(&mut self, size: usize) -> Option<BlockTuple> {
85 if size >= LINE_SIZE {
86 None
87 } else {
88 match self.recyclable_blocks.pop() {
89 x if x.is_null() => None,
90 block => {
91 match unsafe { (*block).scan_block(&*self.line_bitmap, LINE_SIZE as u16 - 1) } {
92 None => {
93 self.handle_full_block(block);
94 self.handle_no_hole(size)
95 }
96 Some((low, high)) => self
97 .scan_for_hole(size, (block, low, high))
98 .or_else(|| self.handle_no_hole(size)),
99 }
100 }
101 }
102 }
103 }
104
105 fn handle_full_block(&mut self, block: *mut Block) {
106 self.unavailable_blocks.push(block);
107 }
108}