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