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