xref: /DragonOS/kernel/crates/ida/src/lib.rs (revision f5b2038871d3441e1c7f32439ff422957e7ab828)
1013ffb70SLoGin #![no_std]
2013ffb70SLoGin #![feature(core_intrinsics)]
3013ffb70SLoGin #![allow(internal_features)]
4013ffb70SLoGin #![allow(clippy::needless_return)]
5013ffb70SLoGin 
6013ffb70SLoGin #[cfg(test)]
7013ffb70SLoGin #[macro_use]
8013ffb70SLoGin extern crate std;
9013ffb70SLoGin 
10013ffb70SLoGin use core::cmp::min;
11013ffb70SLoGin use core::intrinsics::unlikely;
12013ffb70SLoGin use core::marker::PhantomData;
13013ffb70SLoGin use core::ops::Deref;
14013ffb70SLoGin 
15013ffb70SLoGin struct EmptyIdaItemRef<'a> {
16013ffb70SLoGin     _marker: PhantomData<&'a EmptyIdaItem>,
17013ffb70SLoGin }
18013ffb70SLoGin 
19013ffb70SLoGin impl<'a> Deref for EmptyIdaItemRef<'a> {
20013ffb70SLoGin     type Target = EmptyIdaItem;
21013ffb70SLoGin 
22013ffb70SLoGin     fn deref(&self) -> &Self::Target {
23013ffb70SLoGin         &EmptyIdaItem
24013ffb70SLoGin     }
25013ffb70SLoGin }
26013ffb70SLoGin 
27013ffb70SLoGin struct EmptyIdaItem;
28013ffb70SLoGin 
29013ffb70SLoGin unsafe impl kdepends::xarray::ItemEntry for EmptyIdaItem {
30013ffb70SLoGin     type Ref<'a> = EmptyIdaItemRef<'a> where Self: 'a;
31013ffb70SLoGin 
32013ffb70SLoGin     fn into_raw(self) -> *const () {
33013ffb70SLoGin         core::ptr::null()
34013ffb70SLoGin     }
35013ffb70SLoGin 
36013ffb70SLoGin     unsafe fn from_raw(_raw: *const ()) -> Self {
37013ffb70SLoGin         EmptyIdaItem
38013ffb70SLoGin     }
39013ffb70SLoGin 
40013ffb70SLoGin     unsafe fn raw_as_ref<'a>(_raw: *const ()) -> Self::Ref<'a> {
41013ffb70SLoGin         EmptyIdaItemRef {
42013ffb70SLoGin             _marker: PhantomData,
43013ffb70SLoGin         }
44013ffb70SLoGin     }
45013ffb70SLoGin }
46013ffb70SLoGin /// id分配器
47013ffb70SLoGin pub struct IdAllocator {
48013ffb70SLoGin     current_id: usize,
49013ffb70SLoGin     min_id: usize,
50013ffb70SLoGin     max_id: usize,
51013ffb70SLoGin     used: usize,
52013ffb70SLoGin     xarray: kdepends::xarray::XArray<EmptyIdaItem>,
53013ffb70SLoGin }
54013ffb70SLoGin 
55013ffb70SLoGin impl IdAllocator {
56013ffb70SLoGin     /// 创建一个新的id分配器
57013ffb70SLoGin     pub const fn new(initial_id: usize, max_id: usize) -> Option<Self> {
58013ffb70SLoGin         if initial_id >= max_id {
59013ffb70SLoGin             return None;
60013ffb70SLoGin         }
61013ffb70SLoGin         Some(Self {
62013ffb70SLoGin             current_id: initial_id,
63013ffb70SLoGin             min_id: initial_id,
64013ffb70SLoGin             max_id,
65013ffb70SLoGin             used: 0,
66013ffb70SLoGin             xarray: kdepends::xarray::XArray::new(),
67013ffb70SLoGin         })
68013ffb70SLoGin     }
69013ffb70SLoGin 
70013ffb70SLoGin     /// 可用的id数量
71013ffb70SLoGin     #[inline]
72013ffb70SLoGin     pub fn available(&self) -> usize {
73013ffb70SLoGin         self.max_id - self.min_id - self.used
74013ffb70SLoGin     }
75013ffb70SLoGin 
76013ffb70SLoGin     /// 分配一个新的id
77013ffb70SLoGin     ///
78013ffb70SLoGin     /// ## 返回
79013ffb70SLoGin     ///
80013ffb70SLoGin     /// 如果分配成功,返回Some(id),否则返回None
81013ffb70SLoGin     pub fn alloc(&mut self) -> Option<usize> {
82013ffb70SLoGin         if unlikely(self.available() == 0) {
83013ffb70SLoGin             return None;
84013ffb70SLoGin         }
85013ffb70SLoGin 
86013ffb70SLoGin         if let Some(try1) = self.do_find_first_free_index(self.current_id, self.max_id) {
87013ffb70SLoGin             self.current_id = try1;
88013ffb70SLoGin             self.xarray.store(try1 as u64, EmptyIdaItem);
89013ffb70SLoGin             self.used += 1;
90013ffb70SLoGin             return Some(try1);
91013ffb70SLoGin         }
92013ffb70SLoGin 
93013ffb70SLoGin         // 从头开始找
94013ffb70SLoGin         if let Some(try2) =
95013ffb70SLoGin             self.do_find_first_free_index(self.min_id, min(self.current_id, self.max_id))
96013ffb70SLoGin         {
97013ffb70SLoGin             self.current_id = try2;
98013ffb70SLoGin             self.xarray.store(try2 as u64, EmptyIdaItem);
99013ffb70SLoGin             self.used += 1;
100013ffb70SLoGin             return Some(try2);
101013ffb70SLoGin         }
102013ffb70SLoGin         return None;
103013ffb70SLoGin     }
104013ffb70SLoGin 
105013ffb70SLoGin     /// 检查id是否存在
106013ffb70SLoGin     ///
107013ffb70SLoGin     /// ## 参数
108013ffb70SLoGin     ///
109013ffb70SLoGin     /// - `id`:要检查的id
110013ffb70SLoGin     ///
111013ffb70SLoGin     /// ## 返回
112013ffb70SLoGin     ///
113013ffb70SLoGin     /// 如果id存在,返回true,否则返回false
114013ffb70SLoGin     pub fn exists(&self, id: usize) -> bool {
115013ffb70SLoGin         if id < self.min_id || id >= self.max_id {
116013ffb70SLoGin             return false;
117013ffb70SLoGin         }
118013ffb70SLoGin         self.xarray.load(id as u64).is_some()
119013ffb70SLoGin     }
120013ffb70SLoGin 
121013ffb70SLoGin     fn do_find_first_free_index(&self, start_id: usize, end: usize) -> Option<usize> {
122013ffb70SLoGin         (start_id..end).find(|&i| !self.exists(i))
123013ffb70SLoGin     }
124013ffb70SLoGin 
125013ffb70SLoGin     /// 释放一个id
126013ffb70SLoGin     ///
127013ffb70SLoGin     /// ## 参数
128013ffb70SLoGin     ///
129013ffb70SLoGin     /// - `id`:要释放的id
130013ffb70SLoGin     pub fn free(&mut self, id: usize) {
131013ffb70SLoGin         if id < self.min_id || id >= self.max_id {
132013ffb70SLoGin             return;
133013ffb70SLoGin         }
134013ffb70SLoGin         if self.xarray.remove(id as u64).is_some() {
135013ffb70SLoGin             self.used -= 1;
136013ffb70SLoGin         }
137013ffb70SLoGin     }
138013ffb70SLoGin 
139013ffb70SLoGin     /// 返回已经使用的id数量
140013ffb70SLoGin     pub fn used(&self) -> usize {
141013ffb70SLoGin         self.used
142013ffb70SLoGin     }
143*f5b20388Scodeironman 
144*f5b20388Scodeironman     /// 返回最大id数
145*f5b20388Scodeironman     pub fn get_max_id(&self) -> usize {
146*f5b20388Scodeironman         self.max_id
147*f5b20388Scodeironman     }
148013ffb70SLoGin }
149013ffb70SLoGin 
150013ffb70SLoGin impl core::fmt::Debug for IdAllocator {
151013ffb70SLoGin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152013ffb70SLoGin         f.debug_struct("IdAllocator")
153013ffb70SLoGin             .field("current_id", &self.current_id)
154013ffb70SLoGin             .field("min_id", &self.min_id)
155013ffb70SLoGin             .field("max_id", &self.max_id)
156013ffb70SLoGin             .field("used", &self.used)
157013ffb70SLoGin             .field("xarray", &"xarray<()>")
158013ffb70SLoGin             .finish()
159013ffb70SLoGin     }
160013ffb70SLoGin }
161013ffb70SLoGin 
162013ffb70SLoGin #[cfg(test)]
163013ffb70SLoGin mod tests {
164013ffb70SLoGin     use super::*;
165013ffb70SLoGin     #[test]
166013ffb70SLoGin     fn test_new_fail() {
167013ffb70SLoGin         assert_eq!(IdAllocator::new(10, 10).is_none(), true);
168013ffb70SLoGin         assert_eq!(IdAllocator::new(11, 10).is_none(), true);
169013ffb70SLoGin     }
170013ffb70SLoGin     #[test]
171013ffb70SLoGin     fn test_new_success() {
172013ffb70SLoGin         assert_eq!(IdAllocator::new(9, 10).is_some(), true);
173013ffb70SLoGin         assert_eq!(IdAllocator::new(0, 10).is_some(), true);
174013ffb70SLoGin     }
175013ffb70SLoGin 
176013ffb70SLoGin     #[test]
177013ffb70SLoGin     fn test_id_allocator() {
178013ffb70SLoGin         let mut ida = IdAllocator::new(0, 10).unwrap();
179013ffb70SLoGin         assert_eq!(ida.alloc(), Some(0));
180013ffb70SLoGin         assert_eq!(ida.alloc(), Some(1));
181013ffb70SLoGin         assert_eq!(ida.alloc(), Some(2));
182013ffb70SLoGin         assert_eq!(ida.alloc(), Some(3));
183013ffb70SLoGin         assert_eq!(ida.alloc(), Some(4));
184013ffb70SLoGin         assert_eq!(ida.alloc(), Some(5));
185013ffb70SLoGin         assert_eq!(ida.alloc(), Some(6));
186013ffb70SLoGin         assert_eq!(ida.alloc(), Some(7));
187013ffb70SLoGin         assert_eq!(ida.alloc(), Some(8));
188013ffb70SLoGin         assert_eq!(ida.alloc(), Some(9));
189013ffb70SLoGin         assert_eq!(ida.alloc(), None);
190013ffb70SLoGin 
191013ffb70SLoGin         for i in 0..10 {
192013ffb70SLoGin             assert_eq!(ida.exists(i), true);
193013ffb70SLoGin         }
194013ffb70SLoGin 
195013ffb70SLoGin         ida.free(5);
196013ffb70SLoGin 
197013ffb70SLoGin         for i in 0..10 {
198013ffb70SLoGin             if i == 5 {
199013ffb70SLoGin                 assert_eq!(ida.exists(i), false);
200013ffb70SLoGin             } else {
201013ffb70SLoGin                 assert_eq!(ida.exists(i), true);
202013ffb70SLoGin             }
203013ffb70SLoGin         }
204013ffb70SLoGin         assert_eq!(ida.used(), 9);
205013ffb70SLoGin         assert_eq!(ida.alloc(), Some(5));
206013ffb70SLoGin         assert_eq!(ida.alloc(), None);
207013ffb70SLoGin 
208013ffb70SLoGin         assert_eq!(ida.used(), 10);
209013ffb70SLoGin         for i in 0..10 {
210013ffb70SLoGin             ida.free(i);
211013ffb70SLoGin         }
212013ffb70SLoGin 
213013ffb70SLoGin         assert_eq!(ida.used(), 0);
214013ffb70SLoGin     }
215013ffb70SLoGin }
216