1use gc_lite::{GcHeap, GcRef, GcResult, GcTrace, GcTraceCtx, gc_type_register};
13
14#[derive(Debug)]
15struct MyString(String);
16
17impl PartialEq<str> for MyString {
18 fn eq(&self, other: &str) -> bool {
19 self.0 == other
20 }
21}
22
23impl GcTrace for MyString {
24 fn trace(&self, _: &mut GcTraceCtx) {}
25}
26
27impl std::fmt::Display for MyString {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 self.0.fmt(f)
30 }
31}
32
33gc_type_register! {
34 MyString;
35 CyclicNode;
36 TreeNode;
37 DataContainer;
38 TestData;
39}
40
41fn new_heap() -> GcHeap {
42 GcHeap::new(&GC_TYPE_REGISTRY)
43}
44
45fn main() -> GcResult<()> {
46 println!("=== Advanced features example of partitioned garbage collection system ===");
47
48 let mut heap = new_heap();
49 let partition = heap.create_partition(64 * 1024, 16 * 1024);
50
51 println!("\n=== Weak reference functionality demonstration ===");
53 demonstrate_weak_references(&mut heap, partition)?;
54
55 println!("\n=== Circular reference handling demonstration ===");
57 demonstrate_cyclic_references(&mut heap, partition)?;
58
59 println!("\n=== Complex data structures demonstration ===");
61 demonstrate_complex_structures(&mut heap, partition)?;
62
63 println!("\n=== Reference recovery functionality demonstration ===");
65 demonstrate_reference_recovery(&mut heap, partition)?;
66
67 println!("\n=== Cross-context detection demonstration ===");
69 demonstrate_cross_context_detection()?;
70
71 println!("\nAll advanced feature demonstrations completed!");
72 Ok(())
73}
74
75fn demonstrate_weak_references(
77 heap: &mut GcHeap,
78 partition: gc_lite::GcPartitionId,
79) -> GcResult<()> {
80 println!("1. Create strong and weak references...");
81
82 let strong_ref =
83 unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
84 .map_err(|(err, _)| err)?;
85
86 let weak_ref = heap.downgrade(&strong_ref);
87 println!(" Created strong reference: {:?}", strong_ref);
88 println!(" Created weak reference: {:?}", weak_ref);
89
90 println!("\n2. Upgrade weak reference...");
92 match weak_ref.upgrade(heap) {
93 Some(upgraded) => {
94 let data = &*upgraded;
95 println!(" Weak reference upgrade successful: '{}'", data);
96 assert_eq!(data, "Strong Reference Data");
97 }
98 None => println!(" Weak reference upgrade failed"),
99 }
100
101 println!("\n3. Upgrade weak reference after releasing strong reference...");
103 heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
104
105 match weak_ref.upgrade(heap) {
106 Some(_) => {
107 println!(" Weak reference can still be upgraded (object may still be in memory)")
108 }
109 None => println!(" Weak reference upgrade failed (object has been collected)"),
110 }
111
112 Ok(())
113}
114
115fn demonstrate_cyclic_references(
117 heap: &mut GcHeap,
118 partition: gc_lite::GcPartitionId,
119) -> GcResult<()> {
120 println!("1. Create circular reference nodes...");
121
122 let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
124 .map_err(|(err, _)| err)?;
125 let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
126 .map_err(|(err, _)| err)?;
127
128 {
130 unsafe {
131 node1.with_write_barrier(heap, |n| n.set_partner(node2));
132 }
133 unsafe {
134 node2.with_write_barrier(heap, |n| n.set_partner(node1));
135 }
136 }
137
138 println!(" Created node1: {}", unsafe { node1.as_ref() });
139 println!(" Created node2: {}", unsafe { node2.as_ref() });
140
141 println!("\n2. Trigger garbage collection (circular references still exist)...");
143 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" 回收了 {} 字节内存", freed);
145
146 println!("\n3. Verify circular references...");
148 println!(
149 " Node1's partner: {}",
150 unsafe { node1.as_ref() }.get_partner_name()
151 );
152 println!(
153 " Node2's partner: {}",
154 unsafe { node2.as_ref() }.get_partner_name()
155 );
156
157 println!("\n4. Clear root object status and trigger GC again...");
159 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
160 println!(
161 " Freed {} bytes of memory (circular references correctly collected)",
162 freed
163 );
164
165 Ok(())
166}
167
168fn demonstrate_complex_structures(
170 heap: &mut GcHeap,
171 partition: gc_lite::GcPartitionId,
172) -> GcResult<()> {
173 println!("1. Create complex data structures...");
174
175 let mut root_node =
177 unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
178 let mut child1 =
179 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
180 let child2 =
181 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
182 let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
183 .map_err(|(err, _)| err)?;
184
185 {
187 unsafe {
188 root_node.with_write_barrier(heap, |n| n.add_child(child1));
189 }
190 unsafe {
191 root_node.with_write_barrier(heap, |n| n.add_child(child2));
192 }
193 unsafe {
194 child1.with_write_barrier(heap, |n| n.add_child(grandchild));
195 }
196 }
197
198 let container = unsafe {
200 heap.alloc_root_raw(
201 partition,
202 DataContainer {
203 root: root_node,
204 metadata: vec![1, 2, 3],
205 optional_data: Some(child1),
206 },
207 )
208 }
209 .map_err(|(err, _)| err)?;
210
211 println!(" Created tree structure:");
212 println!(" Root -> Child 1 -> Grandchild");
213 println!(" Root -> Child 2");
214 println!(" Created data container");
215
216 println!("\n2. Trigger garbage collection...");
218 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
219 println!(" 回收了 {} 字节内存", freed);
220
221 println!("\n3. Verify data structure integrity...");
223 {
224 let container_ref = unsafe { container.as_ref() };
225 println!(
226 " Container root node: {}",
227 unsafe { container_ref.root.as_ref() }.name
228 );
229 println!(" Metadata length: {}", container_ref.metadata.len());
230 println!(
231 " Optional data exists: {}",
232 container_ref.optional_data.is_some()
233 );
234 }
235
236 Ok(())
237}
238
239fn demonstrate_reference_recovery(
241 heap: &mut GcHeap,
242 partition: gc_lite::GcPartitionId,
243) -> GcResult<()> {
244 println!("1. Create object and get reference...");
245
246 let original_ref = unsafe {
247 heap.alloc_raw(
248 partition,
249 TestData {
250 value: 42,
251 name: "test".to_string(),
252 },
253 )
254 }
255 .map_err(|(err, _)| err)?;
256
257 let data_ref = unsafe { original_ref.as_ref() };
258 println!(" Original reference: {:?}", original_ref);
259 println!(" Data: {:?}", data_ref);
260
261 println!("\n2. Recover GcRef from reference...");
263 let recovered_ref = unsafe { GcRef::try_from_ref(heap, data_ref) };
264
265 match recovered_ref {
266 Some(recovered) => {
267 println!(" Recovery successful: {:?}", recovered);
268 let recovered_data = unsafe { recovered.as_ref() };
269 println!(" Recovered data: {:?}", recovered_data);
270 println!(" Data equal: {}", data_ref == recovered_data);
271 println!(" Reference equal: {}", original_ref == recovered);
272 }
273 None => println!(" Recovery failed (possibly type registration issue)"),
274 }
275
276 println!("\n3. Test invalid reference recovery...");
278 let local_data = TestData {
279 value: 100,
280 name: "local".to_string(),
281 };
282 let invalid_result = unsafe { GcRef::try_from_ref(heap, &local_data) };
283 println!(
284 " Invalid reference recovery result: {:?} (should be None)",
285 invalid_result
286 );
287
288 Ok(())
289}
290
291fn demonstrate_cross_context_detection() -> GcResult<()> {
293 println!("1. Create two independent heaps...");
294
295 let mut heap1 = new_heap();
296 let mut heap2 = new_heap();
297
298 let partition1 = heap1.create_partition(64 * 1024, 16 * 1024);
299 let partition2 = heap2.create_partition(64 * 1024, 16 * 1024);
300
301 let obj1 = unsafe {
302 heap1.alloc_root_raw(
303 partition1,
304 TestData {
305 value: 1,
306 name: "obj1".to_string(),
307 },
308 )
309 }
310 .map_err(|(e, _)| e)?;
311 let obj2 = unsafe {
312 heap2.alloc_raw(
313 partition2,
314 TestData {
315 value: 2,
316 name: "obj2".to_string(),
317 },
318 )
319 }
320 .map_err(|(e, _)| e)?;
321
322 println!("2. Test object source detection...");
323 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
324 assert!(
325 !heap1.contains(obj2.node_ptr()),
326 "obj2 should not be from heap1"
327 );
328 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
329 assert!(
330 !heap2.contains(obj1.node_ptr()),
331 "obj1 should not be from heap2"
332 );
333
334 println!(" ✓ Cross-context detection correct");
335
336 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
338 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
339
340 Ok(())
341}
342
343#[derive(Debug)]
347struct CyclicNode {
348 name: String,
349 partner: Option<GcRef<CyclicNode>>,
350}
351
352impl CyclicNode {
353 fn new(name: &str) -> Self {
354 Self {
355 name: name.to_string(),
356 partner: None,
357 }
358 }
359
360 fn set_partner(&mut self, partner: GcRef<CyclicNode>) {
361 self.partner = Some(partner);
362 }
363
364 fn get_partner_name(&self) -> String {
365 self.partner
366 .map(|p| unsafe { p.as_ref() }.name.clone())
367 .unwrap_or_else(|| "None".to_string())
368 }
369}
370
371impl GcTrace for CyclicNode {
372 fn trace(&self, tr: &mut GcTraceCtx) {
373 if let Some(partner) = self.partner {
374 tr.add(partner);
375 }
376 }
377}
378
379impl std::fmt::Display for CyclicNode {
380 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
381 write!(f, "CyclicNode({})", self.name)
382 }
383}
384
385#[derive(Debug)]
387struct TreeNode {
388 name: String,
389 children: Vec<GcRef<TreeNode>>,
390}
391
392impl TreeNode {
393 fn new(name: &str) -> Self {
394 Self {
395 name: name.to_string(),
396 children: Vec::new(),
397 }
398 }
399
400 fn add_child(&mut self, child: GcRef<TreeNode>) {
401 self.children.push(child);
402 }
403}
404
405impl GcTrace for TreeNode {
406 fn trace(&self, tr: &mut GcTraceCtx) {
407 for child in &self.children {
408 tr.add(*child);
409 }
410 }
411}
412
413impl std::fmt::Display for TreeNode {
414 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
415 write!(
416 f,
417 "TreeNode({}, {} children)",
418 self.name,
419 self.children.len()
420 )
421 }
422}
423
424#[derive(Debug)]
426struct DataContainer {
427 root: GcRef<TreeNode>,
428 metadata: Vec<i32>,
429 optional_data: Option<GcRef<TreeNode>>,
430}
431
432impl GcTrace for DataContainer {
433 fn trace(&self, tr: &mut GcTraceCtx) {
434 tr.add(self.root);
435 if let Some(data) = self.optional_data {
436 tr.add(data);
437 }
438 }
439}
440
441#[derive(Debug, PartialEq)]
443struct TestData {
444 value: i32,
445 name: String,
446}
447
448impl GcTrace for TestData {
449 fn trace(&self, _: &mut GcTraceCtx) {
450 }
452}