1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Liveness token for borrowed userdata references.
//!
//! [`RefAliveToken`] is an `Rc<Cell<bool>>` wrapper that tracks whether the
//! backing data for a [`Borrowed`](crate::LuaUserdata) userdata is still alive.
//!
//! # Lifecycle
//!
//! 1. **Owned userdata** (`LuaUserdata::new`): creates an alive token on construction.
//! When the userdata is GC-collected, the token flips to `false`.
//! 2. **Borrowed userdata** (`LuaUserdata::from_ptr`): shares a token created by
//! the parent (or a scope). When the parent is dropped, all borrowed children
//! see `is_alive() == false`.
//! 3. **Scope** (`Scope::create_userdata_ref`): shares the scope's token. When the
//! scope ends, all scoped userdata become expired.
//!
//! # Usage in structs
//!
//! Mark a field with `#[lua(ref)]` to enable `IntoLua for &T` / `IntoLua for &mut T`:
//!
//! ```ignore
//! #[derive(LuaUserData)]
//! struct Entity {
//! pub name: String,
//! pub pos: Position,
//!
//! alive: RefAliveToken, // enables &Entity → Lua conversion
//! }
//! ```
use Cell;
use fmt;
use Rc;
// ============================================================================
// RefAliveToken — liveness tracking
// ============================================================================
/// A liveness token tied to a parent [`LuaUserdata`](crate::LuaUserdata).
///
/// Each sub-reference holds one token. When the parent userdata is GC-collected
/// (only for owned storage), the token becomes expired and all sub-references
/// will return errors on access.
///
/// `!Send + !Sync` (contains `Rc`).