xref: /DragonOS/kernel/crates/ida/src/lib.rs (revision 013ffb708fab7760ea999c1edf462c69ac68f0ac)
1*013ffb70SLoGin #![no_std]
2*013ffb70SLoGin #![feature(core_intrinsics)]
3*013ffb70SLoGin #![allow(internal_features)]
4*013ffb70SLoGin #![allow(clippy::needless_return)]
5*013ffb70SLoGin 
6*013ffb70SLoGin #[cfg(test)]
7*013ffb70SLoGin #[macro_use]
8*013ffb70SLoGin extern crate std;
9*013ffb70SLoGin 
10*013ffb70SLoGin use core::cmp::min;
11*013ffb70SLoGin use core::intrinsics::unlikely;
12*013ffb70SLoGin use core::marker::PhantomData;
13*013ffb70SLoGin use core::ops::Deref;
14*013ffb70SLoGin 
15*013ffb70SLoGin struct EmptyIdaItemRef<'a> {
16*013ffb70SLoGin     _marker: PhantomData<&'a EmptyIdaItem>,
17*013ffb70SLoGin }
18*013ffb70SLoGin 
19*013ffb70SLoGin impl<'a> Deref for EmptyIdaItemRef<'a> {
20*013ffb70SLoGin     type Target = EmptyIdaItem;
21*013ffb70SLoGin 
22*013ffb70SLoGin     fn deref(&self) -> &Self::Target {
23*013ffb70SLoGin         &EmptyIdaItem
24*013ffb70SLoGin     }
25*013ffb70SLoGin }
26*013ffb70SLoGin 
27*013ffb70SLoGin struct EmptyIdaItem;
28*013ffb70SLoGin 
29*013ffb70SLoGin unsafe impl kdepends::xarray::ItemEntry for EmptyIdaItem {
30*013ffb70SLoGin     type Ref<'a> = EmptyIdaItemRef<'a> where Self: 'a;
31*013ffb70SLoGin 
32*013ffb70SLoGin     fn into_raw(self) -> *const () {
33*013ffb70SLoGin         core::ptr::null()
34*013ffb70SLoGin     }
35*013ffb70SLoGin 
36*013ffb70SLoGin     unsafe fn from_raw(_raw: *const ()) -> Self {
37*013ffb70SLoGin         EmptyIdaItem
38*013ffb70SLoGin     }
39*013ffb70SLoGin 
40*013ffb70SLoGin     unsafe fn raw_as_ref<'a>(_raw: *const ()) -> Self::Ref<'a> {
41*013ffb70SLoGin         EmptyIdaItemRef {
42*013ffb70SLoGin             _marker: PhantomData,
43*013ffb70SLoGin         }
44*013ffb70SLoGin     }
45*013ffb70SLoGin }
46*013ffb70SLoGin /// id分配器
47*013ffb70SLoGin pub struct IdAllocator {
48*013ffb70SLoGin     current_id: usize,
49*013ffb70SLoGin     min_id: usize,
50*013ffb70SLoGin     max_id: usize,
51*013ffb70SLoGin     used: usize,
52*013ffb70SLoGin     xarray: kdepends::xarray::XArray<EmptyIdaItem>,
53*013ffb70SLoGin }
54*013ffb70SLoGin 
55*013ffb70SLoGin impl IdAllocator {
56*013ffb70SLoGin     /// 创建一个新的id分配器
57*013ffb70SLoGin     pub const fn new(initial_id: usize, max_id: usize) -> Option<Self> {
58*013ffb70SLoGin         if initial_id >= max_id {
59*013ffb70SLoGin             return None;
60*013ffb70SLoGin         }
61*013ffb70SLoGin         Some(Self {
62*013ffb70SLoGin             current_id: initial_id,
63*013ffb70SLoGin             min_id: initial_id,
64*013ffb70SLoGin             max_id,
65*013ffb70SLoGin             used: 0,
66*013ffb70SLoGin             xarray: kdepends::xarray::XArray::new(),
67*013ffb70SLoGin         })
68*013ffb70SLoGin     }
69*013ffb70SLoGin 
70*013ffb70SLoGin     /// 可用的id数量
71*013ffb70SLoGin     #[inline]
72*013ffb70SLoGin     pub fn available(&self) -> usize {
73*013ffb70SLoGin         self.max_id - self.min_id - self.used
74*013ffb70SLoGin     }
75*013ffb70SLoGin 
76*013ffb70SLoGin     /// 分配一个新的id
77*013ffb70SLoGin     ///
78*013ffb70SLoGin     /// ## 返回
79*013ffb70SLoGin     ///
80*013ffb70SLoGin     /// 如果分配成功,返回Some(id),否则返回None
81*013ffb70SLoGin     pub fn alloc(&mut self) -> Option<usize> {
82*013ffb70SLoGin         if unlikely(self.available() == 0) {
83*013ffb70SLoGin             return None;
84*013ffb70SLoGin         }
85*013ffb70SLoGin 
86*013ffb70SLoGin         if let Some(try1) = self.do_find_first_free_index(self.current_id, self.max_id) {
87*013ffb70SLoGin             self.current_id = try1;
88*013ffb70SLoGin             self.xarray.store(try1 as u64, EmptyIdaItem);
89*013ffb70SLoGin             self.used += 1;
90*013ffb70SLoGin             return Some(try1);
91*013ffb70SLoGin         }
92*013ffb70SLoGin 
93*013ffb70SLoGin         // 从头开始找
94*013ffb70SLoGin         if let Some(try2) =
95*013ffb70SLoGin             self.do_find_first_free_index(self.min_id, min(self.current_id, self.max_id))
96*013ffb70SLoGin         {
97*013ffb70SLoGin             self.current_id = try2;
98*013ffb70SLoGin             self.xarray.store(try2 as u64, EmptyIdaItem);
99*013ffb70SLoGin             self.used += 1;
100*013ffb70SLoGin             return Some(try2);
101*013ffb70SLoGin         }
102*013ffb70SLoGin         return None;
103*013ffb70SLoGin     }
104*013ffb70SLoGin 
105*013ffb70SLoGin     /// 检查id是否存在
106*013ffb70SLoGin     ///
107*013ffb70SLoGin     /// ## 参数
108*013ffb70SLoGin     ///
109*013ffb70SLoGin     /// - `id`:要检查的id
110*013ffb70SLoGin     ///
111*013ffb70SLoGin     /// ## 返回
112*013ffb70SLoGin     ///
113*013ffb70SLoGin     /// 如果id存在,返回true,否则返回false
114*013ffb70SLoGin     pub fn exists(&self, id: usize) -> bool {
115*013ffb70SLoGin         if id < self.min_id || id >= self.max_id {
116*013ffb70SLoGin             return false;
117*013ffb70SLoGin         }
118*013ffb70SLoGin         self.xarray.load(id as u64).is_some()
119*013ffb70SLoGin     }
120*013ffb70SLoGin 
121*013ffb70SLoGin     fn do_find_first_free_index(&self, start_id: usize, end: usize) -> Option<usize> {
122*013ffb70SLoGin         (start_id..end).find(|&i| !self.exists(i))
123*013ffb70SLoGin     }
124*013ffb70SLoGin 
125*013ffb70SLoGin     /// 释放一个id
126*013ffb70SLoGin     ///
127*013ffb70SLoGin     /// ## 参数
128*013ffb70SLoGin     ///
129*013ffb70SLoGin     /// - `id`:要释放的id
130*013ffb70SLoGin     pub fn free(&mut self, id: usize) {
131*013ffb70SLoGin         if id < self.min_id || id >= self.max_id {
132*013ffb70SLoGin             return;
133*013ffb70SLoGin         }
134*013ffb70SLoGin         if self.xarray.remove(id as u64).is_some() {
135*013ffb70SLoGin             self.used -= 1;
136*013ffb70SLoGin         }
137*013ffb70SLoGin     }
138*013ffb70SLoGin 
139*013ffb70SLoGin     /// 返回已经使用的id数量
140*013ffb70SLoGin     pub fn used(&self) -> usize {
141*013ffb70SLoGin         self.used
142*013ffb70SLoGin     }
143*013ffb70SLoGin }
144*013ffb70SLoGin 
145*013ffb70SLoGin impl core::fmt::Debug for IdAllocator {
146*013ffb70SLoGin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
147*013ffb70SLoGin         f.debug_struct("IdAllocator")
148*013ffb70SLoGin             .field("current_id", &self.current_id)
149*013ffb70SLoGin             .field("min_id", &self.min_id)
150*013ffb70SLoGin             .field("max_id", &self.max_id)
151*013ffb70SLoGin             .field("used", &self.used)
152*013ffb70SLoGin             .field("xarray", &"xarray<()>")
153*013ffb70SLoGin             .finish()
154*013ffb70SLoGin     }
155*013ffb70SLoGin }
156*013ffb70SLoGin 
157*013ffb70SLoGin #[cfg(test)]
158*013ffb70SLoGin mod tests {
159*013ffb70SLoGin     use super::*;
160*013ffb70SLoGin     #[test]
161*013ffb70SLoGin     fn test_new_fail() {
162*013ffb70SLoGin         assert_eq!(IdAllocator::new(10, 10).is_none(), true);
163*013ffb70SLoGin         assert_eq!(IdAllocator::new(11, 10).is_none(), true);
164*013ffb70SLoGin     }
165*013ffb70SLoGin     #[test]
166*013ffb70SLoGin     fn test_new_success() {
167*013ffb70SLoGin         assert_eq!(IdAllocator::new(9, 10).is_some(), true);
168*013ffb70SLoGin         assert_eq!(IdAllocator::new(0, 10).is_some(), true);
169*013ffb70SLoGin     }
170*013ffb70SLoGin 
171*013ffb70SLoGin     #[test]
172*013ffb70SLoGin     fn test_id_allocator() {
173*013ffb70SLoGin         let mut ida = IdAllocator::new(0, 10).unwrap();
174*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(0));
175*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(1));
176*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(2));
177*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(3));
178*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(4));
179*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(5));
180*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(6));
181*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(7));
182*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(8));
183*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(9));
184*013ffb70SLoGin         assert_eq!(ida.alloc(), None);
185*013ffb70SLoGin 
186*013ffb70SLoGin         for i in 0..10 {
187*013ffb70SLoGin             assert_eq!(ida.exists(i), true);
188*013ffb70SLoGin         }
189*013ffb70SLoGin 
190*013ffb70SLoGin         ida.free(5);
191*013ffb70SLoGin 
192*013ffb70SLoGin         for i in 0..10 {
193*013ffb70SLoGin             if i == 5 {
194*013ffb70SLoGin                 assert_eq!(ida.exists(i), false);
195*013ffb70SLoGin             } else {
196*013ffb70SLoGin                 assert_eq!(ida.exists(i), true);
197*013ffb70SLoGin             }
198*013ffb70SLoGin         }
199*013ffb70SLoGin         assert_eq!(ida.used(), 9);
200*013ffb70SLoGin         assert_eq!(ida.alloc(), Some(5));
201*013ffb70SLoGin         assert_eq!(ida.alloc(), None);
202*013ffb70SLoGin 
203*013ffb70SLoGin         assert_eq!(ida.used(), 10);
204*013ffb70SLoGin         for i in 0..10 {
205*013ffb70SLoGin             ida.free(i);
206*013ffb70SLoGin         }
207*013ffb70SLoGin 
208*013ffb70SLoGin         assert_eq!(ida.used(), 0);
209*013ffb70SLoGin     }
210*013ffb70SLoGin }
211