Skip to main content

sim_lib_gc_tracing/
finalization.rs

1use std::collections::{BTreeMap, BTreeSet};
2
3use sim_lib_mutation::ManagedId;
4
5/// Opaque, language-neutral notification that one unreachable target is ready.
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub struct FinalizationRecord {
8    /// Collector registration identity.
9    pub registration: u64,
10    /// Unreachable managed identity; it is not a live handle.
11    pub target: ManagedId,
12}
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15enum RegistrationState {
16    Registered,
17    Cancelled,
18    Admitted,
19}
20
21/// At-most-once finalization registrations, separate from managed storage.
22#[derive(Default)]
23pub struct FinalizationRegistry {
24    next: u64,
25    entries: BTreeMap<u64, (ManagedId, RegistrationState)>,
26}
27
28impl FinalizationRegistry {
29    /// Registers a target and returns a stable cancellation identity.
30    pub fn register(&mut self, target: ManagedId) -> u64 {
31        let id = self.next;
32        self.next = self.next.saturating_add(1);
33        self.entries
34            .insert(id, (target, RegistrationState::Registered));
35        id
36    }
37    /// Cancels a pending registration. Cancellation is idempotent.
38    pub fn cancel(&mut self, registration: u64) -> bool {
39        let Some((_, state)) = self.entries.get_mut(&registration) else {
40            return false;
41        };
42        if *state != RegistrationState::Registered {
43            return false;
44        }
45        *state = RegistrationState::Cancelled;
46        true
47    }
48    pub(crate) fn ready(&self, swept: &BTreeSet<ManagedId>) -> Vec<FinalizationRecord> {
49        self.entries
50            .iter()
51            .filter_map(|(&registration, &(target, state))| {
52                (state == RegistrationState::Registered && swept.contains(&target)).then_some(
53                    FinalizationRecord {
54                        registration,
55                        target,
56                    },
57                )
58            })
59            .collect()
60    }
61    pub(crate) fn mark_admitted(&mut self, records: &[FinalizationRecord]) {
62        for record in records {
63            if let Some((_, state)) = self.entries.get_mut(&record.registration) {
64                *state = RegistrationState::Admitted;
65            }
66        }
67    }
68}