basic_usage/
basic_usage.rs1use std::ops::Deref;
14
15use gc_lite::{GcHeap, GcRef, GcResult, GcTrace, GcTraceCtx, gc_type_register};
16
17#[derive(Debug)]
18struct MyString(String);
19
20#[derive(Debug)]
21struct MyI32(i32);
22
23impl GcTrace for MyString {
24 fn trace(&self, _: &mut GcTraceCtx) {}
25}
26
27impl GcTrace for MyI32 {
28 fn trace(&self, _: &mut GcTraceCtx) {}
29}
30
31impl std::fmt::Display for MyString {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 self.0.fmt(f)
34 }
35}
36
37impl std::fmt::Display for MyI32 {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 self.0.fmt(f)
40 }
41}
42
43gc_type_register! {
44 MyString, drop_pass = 0;
45 MyI32;
46 TestNode;
47}
48
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 println!("\nTrigger garbage collection for partition1 again...");
141 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 println!("\nDemonstrate automatic garbage collection...");
153
154 let small_partition = heap.create_partition();
156
157 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 println!("\nDemonstrate partition deletion:");
206
207 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}
222#[derive(Debug)]
224struct TestNode {
225 name: String,
226 children: Vec<GcRef<TestNode>>,
227}
228
229impl TestNode {
230 fn new(name: &str) -> Self {
231 Self {
232 name: name.to_string(),
233 children: Vec::new(),
234 }
235 }
236
237 fn add_child(&mut self, child: GcRef<TestNode>) {
238 self.children.push(child);
239 }
240}
241
242impl GcTrace for TestNode {
243 fn trace(&self, tr: &mut GcTraceCtx) {
244 for child in &self.children {
246 tr.add(*child);
247 }
248 }
249}
250
251impl std::fmt::Display for TestNode {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 write!(f, "TestNode({})", self.name)
254 }
255}