Skip to main content

bump_scope/
bump_scope_guard.rs

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