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