Skip to main content

bump_scope/
bump_scope_guard.rs

1use core::{fmt::Debug, num::NonZeroUsize, ptr::NonNull};
2
3use crate::{
4    BumpScope,
5    alloc::Allocator,
6    chunk::ChunkHeader,
7    polyfill::transmute_mut,
8    raw_bump::{RawBump, RawChunk},
9    settings::{BumpAllocatorSettings, BumpSettings},
10    stats::AnyStats,
11};
12
13/// This is returned from [`checkpoint`] and used for [`reset_to`].
14///
15/// [`checkpoint`]: crate::traits::BumpAllocatorCore::checkpoint
16/// [`reset_to`]: crate::traits::BumpAllocatorCore::reset_to
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct Checkpoint {
19    pub(crate) chunk: NonNull<ChunkHeader>,
20    pub(crate) address: NonZeroUsize,
21}
22
23impl Checkpoint {
24    pub(crate) fn new<S: BumpAllocatorSettings>(chunk: RawChunk<S>) -> Self {
25        let address = chunk.pos().addr();
26        let chunk = chunk.header.cast();
27        Checkpoint { chunk, address }
28    }
29
30    pub(crate) unsafe fn reset_within_chunk(self) {
31        unsafe {
32            let ptr = self.chunk.cast::<u8>().with_addr(self.address);
33            self.chunk.as_ref().pos.set(ptr);
34        }
35    }
36}
37
38/// Returned from [`BumpAllocator::scope_guard`].
39///
40/// [`BumpAllocator::scope_guard`]: crate::traits::BumpAllocator::scope_guard
41#[must_use]
42pub struct BumpScopeGuard<'a, A, S = BumpSettings>
43where
44    A: Allocator,
45    S: BumpAllocatorSettings,
46{
47    bump: &'a mut RawBump<A, S>,
48    checkpoint: Checkpoint,
49}
50
51impl<A, S> Debug for BumpScopeGuard<'_, A, S>
52where
53    A: Allocator,
54    S: BumpAllocatorSettings,
55{
56    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57        AnyStats::from(self.bump.stats()).debug_format("BumpScopeGuard", f)
58    }
59}
60
61impl<A, S> Drop for BumpScopeGuard<'_, A, S>
62where
63    A: Allocator,
64    S: BumpAllocatorSettings,
65{
66    #[inline(always)]
67    fn drop(&mut self) {
68        self.reset();
69    }
70}
71
72impl<'a, A, S> BumpScopeGuard<'a, A, S>
73where
74    A: Allocator,
75    S: BumpAllocatorSettings,
76{
77    #[inline(always)]
78    pub(crate) fn new(bump: &'a mut RawBump<A, S>) -> Self {
79        let checkpoint = bump.checkpoint();
80        Self { bump, checkpoint }
81    }
82
83    /// Returns a new `BumpScope`.
84    #[inline(always)]
85    pub fn scope(&mut self) -> &mut BumpScope<'_, A, S> {
86        unsafe { transmute_mut(self.bump) }
87    }
88
89    /// Frees the memory taken up by allocations made since creation of this bump scope guard.
90    #[inline(always)]
91    pub fn reset(&mut self) {
92        unsafe { self.bump.reset_to(self.checkpoint) }
93    }
94}