Skip to main content

cranpose_core/
node_id_cell.rs

1use std::cell::Cell;
2
3use crate::NodeId;
4
5/// A node id or none in one word, where `Cell<Option<NodeId>>` takes two: a
6/// layout node keeps three, and the 24 bytes kept it out of jemalloc's
7/// 640-byte size class.
8pub struct NodeIdCell(Cell<NodeId>);
9
10// The id a cell holds for none: no node gets it, as ids index the applier's
11// nodes.
12const NONE: NodeId = NodeId(usize::MAX);
13
14impl NodeIdCell {
15    /// A cell holding `id`.
16    pub const fn new(id: Option<NodeId>) -> Self {
17        Self(Cell::new(match id {
18            Some(id) => id,
19            None => NONE,
20        }))
21    }
22
23    /// The id the cell holds.
24    pub fn get(&self) -> Option<NodeId> {
25        // With `then_some`, LLVM compiles the composer's group opening five
26        // instructions longer a group.
27        Some(self.0.get()).filter(|&id| id != NONE)
28    }
29
30    /// Puts `id` in the cell.
31    pub fn set(&self, id: Option<NodeId>) {
32        debug_assert_ne!(id, Some(NONE), "no node takes the none id");
33        self.0.set(id.unwrap_or(NONE));
34    }
35
36    /// Puts `id` in the cell and returns the id it held.
37    pub fn replace(&self, id: Option<NodeId>) -> Option<NodeId> {
38        let previous = self.get();
39        self.set(id);
40        previous
41    }
42}