@@ -23,22 +23,22 @@ use crate::bitmap::BitmapVec;
2323/// Basic usage
2424///
2525/// ```
26- /// use kernel::alloc::{ AllocError, flags::GFP_KERNEL} ;
27- /// use kernel::id_pool::IdPool;
26+ /// use kernel::alloc::AllocError;
27+ /// use kernel::id_pool::{ IdPool, UnusedId} ;
2828///
2929/// let mut pool = IdPool::with_capacity(64, GFP_KERNEL)?;
3030/// for i in 0..64 {
31- /// assert_eq!(i, pool.acquire_next_id (i).ok_or(ENOSPC)?);
31+ /// assert_eq!(i, pool.find_unused_id (i).ok_or(ENOSPC)?.acquire() );
3232/// }
3333///
3434/// pool.release_id(23);
35- /// assert_eq!(23, pool.acquire_next_id (0).ok_or(ENOSPC)?);
35+ /// assert_eq!(23, pool.find_unused_id (0).ok_or(ENOSPC)?.acquire() );
3636///
37- /// assert_eq!(None, pool.acquire_next_id(0 )); // time to realloc.
37+ /// assert!( pool.find_unused_id(0).is_none( )); // time to realloc.
3838/// let resizer = pool.grow_request().ok_or(ENOSPC)?.realloc(GFP_KERNEL)?;
3939/// pool.grow(resizer);
4040///
41- /// assert_eq!(pool.acquire_next_id (0), Some(64) );
41+ /// assert_eq!(pool.find_unused_id (0).ok_or(ENOSPC)?.acquire(), 64 );
4242/// # Ok::<(), Error>(())
4343/// ```
4444///
@@ -52,8 +52,8 @@ use crate::bitmap::BitmapVec;
5252/// fn get_id_maybe_realloc(guarded_pool: &SpinLock<IdPool>) -> Result<usize, AllocError> {
5353/// let mut pool = guarded_pool.lock();
5454/// loop {
55- /// match pool.acquire_next_id (0) {
56- /// Some(index) => return Ok(index),
55+ /// match pool.find_unused_id (0) {
56+ /// Some(index) => return Ok(index.acquire() ),
5757/// None => {
5858/// let alloc_request = pool.grow_request();
5959/// drop(pool);
@@ -221,18 +221,18 @@ impl IdPool {
221221 self . map = resizer. new ;
222222 }
223223
224- /// Acquires a new ID by finding and setting the next zero bit in the
225- /// bitmap.
224+ /// Finds an unused ID in the bitmap.
226225 ///
227226 /// Upon success, returns its index. Otherwise, returns [`None`]
228227 /// to indicate that a [`Self::grow_request`] is needed.
229228 #[ inline]
230- pub fn acquire_next_id ( & mut self , offset : usize ) -> Option < usize > {
231- let next_zero_bit = self . map . next_zero_bit ( offset) ;
232- if let Some ( nr) = next_zero_bit {
233- self . map . set_bit ( nr) ;
234- }
235- next_zero_bit
229+ #[ must_use]
230+ pub fn find_unused_id ( & mut self , offset : usize ) -> Option < UnusedId < ' _ > > {
231+ // INVARIANT: `next_zero_bit()` returns None or an integer less than `map.len()`
232+ Some ( UnusedId {
233+ id : self . map . next_zero_bit ( offset) ?,
234+ pool : self ,
235+ } )
236236 }
237237
238238 /// Releases an ID.
@@ -242,6 +242,51 @@ impl IdPool {
242242 }
243243}
244244
245+ /// Represents an unused id in an [`IdPool`].
246+ ///
247+ /// # Invariants
248+ ///
249+ /// The value of `id` is less than `pool.map.len()`.
250+ pub struct UnusedId < ' pool > {
251+ id : usize ,
252+ pool : & ' pool mut IdPool ,
253+ }
254+
255+ impl < ' pool > UnusedId < ' pool > {
256+ /// Get the unused id as an usize.
257+ ///
258+ /// Be aware that the id has not yet been acquired in the pool. The
259+ /// [`acquire`] method must be called to prevent others from taking the id.
260+ ///
261+ /// [`acquire`]: UnusedId::acquire()
262+ #[ inline]
263+ #[ must_use]
264+ pub fn as_usize ( & self ) -> usize {
265+ self . id
266+ }
267+
268+ /// Get the unused id as an u32.
269+ ///
270+ /// Be aware that the id has not yet been acquired in the pool. The
271+ /// [`acquire`] method must be called to prevent others from taking the id.
272+ ///
273+ /// [`acquire`]: UnusedId::acquire()
274+ #[ inline]
275+ #[ must_use]
276+ pub fn as_u32 ( & self ) -> u32 {
277+ // CAST: By the type invariants:
278+ // `self.id < pool.map.len() <= BitmapVec::MAX_LEN = i32::MAX`.
279+ self . id as u32
280+ }
281+
282+ /// Acquire the unused id.
283+ #[ inline]
284+ pub fn acquire ( self ) -> usize {
285+ self . pool . map . set_bit ( self . id ) ;
286+ self . id
287+ }
288+ }
289+
245290impl Default for IdPool {
246291 #[ inline]
247292 fn default ( ) -> Self {
0 commit comments