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
95
96
97
98
99
100
101
102
103
104
105
//! Tokio integration for async-safe allocation (v0.8.0).
//!
//! This module provides async-safe allocation patterns for use with Tokio
//! and other async runtimes. It enforces the hybrid model where frame
//! allocations stay on the main thread and async tasks use pool/heap.
//!
//! # Philosophy
//!
//! - **Opt-in**: Requires `tokio` feature flag
//! - **Safe by default**: All allocations are pool-backed (never frame)
//! - **Task-scoped**: Allocations freed when task completes
//! - **Runtime-agnostic**: Works with Tokio, async-std, smol, etc.
//!
//! # Why Frame Allocations Are Unsafe in Async
//!
//! Frame allocations are tied to frame boundaries (`begin_frame`/`end_frame`).
//! When an async task suspends at an `.await` point, the main thread may call
//! `end_frame()`, invalidating any frame allocations the task holds.
//!
//! # The Hybrid Model
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────┐
//! │ Main Thread (Sync) │ Async Tasks │
//! ├─────────────────────────────────┼───────────────────────────┤
//! │ frame_alloc, frame_box ✓ │ frame_* ❌ UNSAFE │
//! │ pool_alloc, pool_box ✓ │ pool_*, heap_* ✓ SAFE │
//! │ heap_alloc, heap_box ✓ │ TaskAlloc ✓ SAFE │
//! └─────────────────────────────────┴───────────────────────────┘
//! ```
//!
//! # Example
//!
//! ```rust,ignore
//! use framealloc::{SmartAlloc, AllocConfig};
//! use framealloc::tokio::TaskAlloc;
//!
//! let alloc = SmartAlloc::new(AllocConfig::default());
//!
//! // Main thread: frame allocations OK
//! alloc.begin_frame();
//! let scratch = alloc.frame_vec::<f32>();
//!
//! // Spawn async task: use TaskAlloc or pool_*
//! let alloc_clone = alloc.clone();
//! tokio::spawn(async move {
//! let mut task = TaskAlloc::new(&alloc_clone);
//! let data = task.alloc_box(expensive_computation().await);
//! process(&data).await;
//! // task drops → allocations freed
//! });
//!
//! alloc.end_frame();
//! ```
pub use ;
pub use AsyncPoolGuard;