tidu/
checkpoint.rs

1use std::cell::RefCell;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum CheckpointMode {
5    Off,
6    Conservative,
7    Aggressive,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct AdExecutionPolicy {
12    pub checkpoint_mode: CheckpointMode,
13}
14
15impl Default for AdExecutionPolicy {
16    fn default() -> Self {
17        Self {
18            checkpoint_mode: CheckpointMode::Off,
19        }
20    }
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub(crate) enum StorageDecision {
25    Retain,
26    Replay,
27}
28
29/// Public hint used by [`crate::LinearizableOp::checkpoint_hint`] to guide
30/// retain-vs-replay policy decisions.
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum CheckpointHint {
33    CheapReplay,
34    ExpensiveReplay,
35    MustRetain,
36}
37
38thread_local! {
39    static POLICY_STACK: RefCell<Vec<AdExecutionPolicy>> =
40        RefCell::new(vec![AdExecutionPolicy::default()]);
41}
42
43struct PolicyScopeGuard;
44
45impl PolicyScopeGuard {
46    fn push(policy: AdExecutionPolicy) -> Self {
47        POLICY_STACK.with(|stack| stack.borrow_mut().push(policy));
48        Self
49    }
50}
51
52impl Drop for PolicyScopeGuard {
53    fn drop(&mut self) {
54        POLICY_STACK.with(|stack| {
55            let popped = stack.borrow_mut().pop();
56            debug_assert!(popped.is_some());
57        });
58    }
59}
60
61pub fn with_ad_policy<R>(policy: AdExecutionPolicy, f: impl FnOnce() -> R) -> R {
62    let _guard = PolicyScopeGuard::push(policy);
63    f()
64}
65
66pub(crate) fn current_ad_policy() -> AdExecutionPolicy {
67    POLICY_STACK.with(|stack| stack.borrow().last().copied().unwrap_or_default())
68}
69
70pub(crate) fn storage_decision(
71    policy: AdExecutionPolicy,
72    checkpoint_hint: CheckpointHint,
73) -> StorageDecision {
74    match (policy.checkpoint_mode, checkpoint_hint) {
75        (_, CheckpointHint::MustRetain) => StorageDecision::Retain,
76        (CheckpointMode::Off, _) => StorageDecision::Retain,
77        (CheckpointMode::Conservative, CheckpointHint::CheapReplay) => StorageDecision::Replay,
78        (CheckpointMode::Conservative, CheckpointHint::ExpensiveReplay) => StorageDecision::Retain,
79        (CheckpointMode::Aggressive, _) => StorageDecision::Replay,
80    }
81}