Skip to main content

GcRef

Struct GcRef 

Source
pub struct GcRef<T: GcNode> { /* private fields */ }
Expand description

Garbage collection reference

Implementations§

Source§

impl<T: GcNode> GcRef<T>

Source

pub unsafe fn as_ref(&self) -> &T

Access the underlying GC-managed object as a reference.

§Safety

The caller must ensure the GC object is still alive and has not been collected (e.g., it is protected by a root/LOCAL flag, or the GC heap is guaranteed not to run a collection cycle).

Examples found in repository?
examples/gc_node_usage.rs (line 66)
56fn main() -> GcResult<()> {
57    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
58    let partition = heap.create_partition(64 * 1024, 16 * 1024);
59    let stack_id = heap.acquire_scope_stack(partition);
60
61    let static_ref = alloc_static(&mut heap, stack_id, 10)?;
62    let other_ref = alloc_other(&mut heap, stack_id, 20)?;
63
64    println!(
65        "Static node value: {}",
66        unsafe { static_ref.as_ref() }._value
67    );
68    println!("Other node value: {}", unsafe { other_ref.as_ref() }._value);
69
70    heap.release_scope_stack(stack_id);
71
72    println!("gc_node_usage example verified");
73
74    Ok(())
75}
More examples
Hide additional examples
examples/advanced_features.rs (line 138)
116fn demonstrate_cyclic_references(
117    heap: &mut GcHeap,
118    partition: gc_lite::GcPartitionId,
119) -> GcResult<()> {
120    println!("1. Create circular reference nodes...");
121
122    // Create two mutually referencing nodes
123    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    // Establish circular references
129    {
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    // Trigger garbage collection
142    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    // Verify circular references still exist
147    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    // Clear root object status, let circular references be collected
158    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
168/// Demonstrate complex data structures
169fn demonstrate_complex_structures(
170    heap: &mut GcHeap,
171    partition: gc_lite::GcPartitionId,
172) -> GcResult<()> {
173    println!("1. Create complex data structures...");
174
175    // Create multiple nodes
176    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    // Build tree structure
186    {
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    // Create data container
199    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    // Trigger garbage collection
217    println!("\n2. Trigger garbage collection...");
218    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
219    println!("  回收了 {} 字节内存", freed);
220
221    // Verify data structure integrity
222    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
239/// Demonstrate reference recovery functionality
240fn 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    // Recover GcRef from reference
262    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    // Test invalid reference recovery - create an object not in GC heap
277    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
291/// Demonstrate cross-context detection
292fn 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    // Clean up
337    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
338    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
339
340    Ok(())
341}
342
343// Supporting type definitions
344
345/// Circular reference node
346#[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    }
examples/basic_usage.rs (line 72)
47fn main() -> GcResult<()> {
48    println!("=== Basic usage example of partitioned garbage collection system ===");
49
50    // Create garbage collection context
51    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
52
53    println!("Initial state:");
54    println!("  Number of partitions: {}", heap.partition_ids().len());
55
56    // Create two partitions
57    println!("\nCreate partitions:");
58    let partition1 = heap.create_partition(64 * 1024, 16 * 1024);
59    let partition2 = heap.create_partition(64 * 1024, 16 * 1024);
60    println!("  Created partition1: {:?}", partition1);
61    println!("  Created partition2: {:?}", partition2);
62    println!("  Number of partitions: {}", heap.partition_ids().len());
63
64    // Allocate objects in partition1
65    println!("\nAllocate objects in partition1:");
66    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
67        .map_err(|(err, _)| err)?;
68    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
69    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
70        .map_err(|(err, _)| err)?;
71
72    println!("  Created string: '{}'", unsafe { obj1.as_ref() });
73    println!("  Created number: {}", unsafe { obj2.as_ref() });
74    println!("  Created string: '{}'", unsafe { obj3.as_ref() });
75
76    // Allocate objects in partition2
77    println!("\nAllocate objects in partition2:");
78    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
79        .map_err(|(err, _)| err)?;
80    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
81
82    println!("  Created string: '{}'", unsafe { obj4.as_ref() });
83    println!("  Created number: {}", unsafe { obj5.as_ref() });
84
85    // Display partition status
86    println!("\nPartition status:");
87    for partition_id in heap.partition_ids() {
88        if let Some(partition) = heap.partition(partition_id) {
89            let limit = heap.memory_limit();
90            let usage = if limit > 0 {
91                format!(
92                    "{}/{} bytes ({:.1}%)",
93                    partition.memory_used(),
94                    limit,
95                    (partition.memory_used() as f64 / limit as f64) * 100.0
96                )
97            } else {
98                format!("{}/∞ bytes", partition.memory_used())
99            };
100            println!(
101                "  {:?}: {} [自动GC: {}]",
102                partition_id,
103                usage,
104                if heap.gc_threshold() > 0 {
105                    "Enabled"
106                } else {
107                    "Disabled"
108                }
109            );
110        }
111    }
112
113    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
114    // No explicit `set_root` calls are needed for them.
115    println!("\nRoot objects are held by variables:");
116    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
117
118    // Manually trigger garbage collection for partition1
119    println!("\nManually trigger garbage collection for partition1...");
120    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
121    println!("  Collected {} bytes", freed);
122
123    // Verify root objects are still valid
124    println!("\nVerify partition1 root objects are still valid:");
125    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
126    println!("  Object2: {}", unsafe { obj2.as_ref() });
127
128    // Manually trigger garbage collection for partition2
129    println!("\nManually trigger garbage collection for partition2...");
130    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
131    println!("  Collected {} bytes", freed);
132
133    // Verify partition2 root objects are still valid
134    println!("\nVerify partition2 root objects are still valid:");
135    println!("  Object4: '{}'", unsafe { obj4.as_ref() });
136
137    // Trigger garbage collection for partition1 again to collect unreferenced objects
138    println!("\nTrigger garbage collection for partition1 again...");
139    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
140    // to test collection. For this example, we'll just collect other garbage.
141    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  Collected {} bytes", freed);
143
144    // Verify remaining root objects are still valid
145    println!("\nVerify remaining root objects are still valid:");
146    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
147    println!("  Object2: {} (still a root)", unsafe { obj2.as_ref() });
148
149    // Demonstrate automatic garbage collection
150    println!("\nDemonstrate automatic garbage collection...");
151
152    // Create a small partition to demonstrate automatic GC
153    let small_partition = heap.create_partition(64 * 1024, 16 * 1024);
154
155    // Allocate multiple objects to fill partition
156    for i in 0..5 {
157        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
158            .map_err(|(err, _)| err)?;
159    }
160
161    println!("  Allocated 5 objects in small partition");
162
163    // Demonstrate weak references
164    println!("\nDemonstrate weak references:");
165    let weak_ref = heap.downgrade(&obj1);
166    println!("  Created weak reference: {:?}", weak_ref);
167
168    // Upgrade weak reference
169    match weak_ref.upgrade(&heap) {
170        Some(strong_ref) => {
171            println!("  Weak reference upgrade successful: '{}'", &*strong_ref);
172        }
173        None => {
174            println!("  Weak reference upgrade failed");
175        }
176    }
177
178    // Demonstrate complex types with GC references
179    println!("\nDemonstrate complex types with GC references:");
180    let mut node1 =
181        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
182    let mut node2 =
183        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
184
185    // Establish references between nodes
186    {
187        unsafe {
188            node1.with_write_barrier(&mut heap, |n| n.add_child(node2));
189        }
190        unsafe {
191            node2.with_write_barrier(&mut heap, |n| n.add_child(node1));
192        }
193    }
194
195    println!("  Created node1: {}", unsafe { node1.as_ref() });
196    println!("  Created node2: {}", unsafe { node2.as_ref() });
197
198    // Trigger garbage collection, verify circular references are handled correctly
199    println!("\nGarbage collection for handling circular references...");
200    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
201    println!("  回收了 {} 字节内存", freed);
202
203    // Demonstrate partition deletion
204    println!("\nDemonstrate partition deletion:");
205
206    // Create an empty partition
207    let empty_partition = heap.create_partition(64 * 1024, 16 * 1024);
208    println!("  Created empty partition: {:?}", empty_partition);
209
210    // Delete empty partition
211    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
212    println!("  Deleted empty partition successfully");
213
214    // Delete non-empty partition
215    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
216    println!("  Deleted non-empty partition successfully");
217
218    println!("\nExample completed!");
219    Ok(())
220}
Source

pub unsafe fn as_mut(&mut self) -> &mut T

Access the underlying GC-managed object as a mutable reference.

§Safety

Same as as_ref.

Source

pub unsafe fn try_from_ref(heap: &GcHeap, data_ref: &T) -> Option<Self>

Create GcRef from &T reference

§Safety

Caller must ensure the passed reference comes from a valid GC-managed object that was allocated via GcRef<T>. Passing a reference from any other source (stack, heap, etc.) is undefined behavior.

Examples found in repository?
examples/advanced_features.rs (line 263)
240fn 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    // Recover GcRef from reference
262    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    // Test invalid reference recovery - create an object not in GC heap
277    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}
Source

pub unsafe fn from_ref_unchecked(data_ref: &T) -> Self

Unsafe conversion from &T to GcRef, main focus on speed.

§Safety

Caller must ensure &T comes from GcRef, otherwise consequences are unpredictable.

Source

pub unsafe fn with_write_barrier<F, R>( &mut self, heap: &mut GcHeap, mutator: F, ) -> R
where F: FnOnce(&mut T) -> R,

Apply a mutator function to the GC-managed object, with write barrier.

§Safety

The caller must ensure the GC object is still alive and valid. If the mutator writes new GC references into the object, the write barrier will handle tri-color invariant for incremental GC.

Examples found in repository?
examples/advanced_features.rs (line 131)
116fn demonstrate_cyclic_references(
117    heap: &mut GcHeap,
118    partition: gc_lite::GcPartitionId,
119) -> GcResult<()> {
120    println!("1. Create circular reference nodes...");
121
122    // Create two mutually referencing nodes
123    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    // Establish circular references
129    {
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    // Trigger garbage collection
142    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    // Verify circular references still exist
147    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    // Clear root object status, let circular references be collected
158    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
168/// Demonstrate complex data structures
169fn demonstrate_complex_structures(
170    heap: &mut GcHeap,
171    partition: gc_lite::GcPartitionId,
172) -> GcResult<()> {
173    println!("1. Create complex data structures...");
174
175    // Create multiple nodes
176    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    // Build tree structure
186    {
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    // Create data container
199    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    // Trigger garbage collection
217    println!("\n2. Trigger garbage collection...");
218    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
219    println!("  回收了 {} 字节内存", freed);
220
221    // Verify data structure integrity
222    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}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 124)
88fn benchmark_complex_graphs() {
89    let sizes = [100, 500, 1000];
90
91    for &size in &sizes {
92        println!("\nTest complex object graph size: {} nodes", size);
93
94        let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
95        let partition = context.create_partition(64 * 1024, 16 * 1024);
96
97        // Create complex object graph
98        let graph_start = Instant::now();
99        let mut nodes = Vec::new();
100
101        // Create all nodes
102        for _i in 0..size {
103            let node = unsafe {
104                context.alloc_raw(
105                    partition,
106                    GraphNode {
107                        neighbors: Vec::new(),
108                    },
109                )
110            }
111            .unwrap();
112            nodes.push(node);
113        }
114
115        // Establish complex dependencies
116        for i in 0..size {
117            {
118                // Each node points to subsequent nodes
119                for j in 1..=5 {
120                    if i + j < size {
121                        let n = nodes[i + j];
122                        unsafe {
123                            nodes[i]
124                                .with_write_barrier(&mut context, |node| node.neighbors.push(n));
125                        }
126                    }
127                }
128                // Every 10 nodes form a cycle
129                if i % 10 == 0 && i + 9 < size {
130                    let n = nodes[i];
131                    unsafe {
132                        nodes[i + 9]
133                            .with_write_barrier(&mut context, |node| node.neighbors.push(n));
134                    }
135                }
136            }
137        }
138        let graph_duration = graph_start.elapsed();
139
140        println!("  Built complex object graph in: {:?}", graph_duration);
141
142        // Measure GC performance
143        let gc_start = Instant::now();
144        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
145        let gc_duration = gc_start.elapsed();
146
147        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
148        println!(
149            "  Object graph complexity: average {} neighbors per node",
150            if size > 0 { (size * 5) / size } else { 0 }
151        );
152    }
153}
examples/basic_usage.rs (line 188)
47fn main() -> GcResult<()> {
48    println!("=== Basic usage example of partitioned garbage collection system ===");
49
50    // Create garbage collection context
51    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
52
53    println!("Initial state:");
54    println!("  Number of partitions: {}", heap.partition_ids().len());
55
56    // Create two partitions
57    println!("\nCreate partitions:");
58    let partition1 = heap.create_partition(64 * 1024, 16 * 1024);
59    let partition2 = heap.create_partition(64 * 1024, 16 * 1024);
60    println!("  Created partition1: {:?}", partition1);
61    println!("  Created partition2: {:?}", partition2);
62    println!("  Number of partitions: {}", heap.partition_ids().len());
63
64    // Allocate objects in partition1
65    println!("\nAllocate objects in partition1:");
66    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
67        .map_err(|(err, _)| err)?;
68    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
69    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
70        .map_err(|(err, _)| err)?;
71
72    println!("  Created string: '{}'", unsafe { obj1.as_ref() });
73    println!("  Created number: {}", unsafe { obj2.as_ref() });
74    println!("  Created string: '{}'", unsafe { obj3.as_ref() });
75
76    // Allocate objects in partition2
77    println!("\nAllocate objects in partition2:");
78    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
79        .map_err(|(err, _)| err)?;
80    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
81
82    println!("  Created string: '{}'", unsafe { obj4.as_ref() });
83    println!("  Created number: {}", unsafe { obj5.as_ref() });
84
85    // Display partition status
86    println!("\nPartition status:");
87    for partition_id in heap.partition_ids() {
88        if let Some(partition) = heap.partition(partition_id) {
89            let limit = heap.memory_limit();
90            let usage = if limit > 0 {
91                format!(
92                    "{}/{} bytes ({:.1}%)",
93                    partition.memory_used(),
94                    limit,
95                    (partition.memory_used() as f64 / limit as f64) * 100.0
96                )
97            } else {
98                format!("{}/∞ bytes", partition.memory_used())
99            };
100            println!(
101                "  {:?}: {} [自动GC: {}]",
102                partition_id,
103                usage,
104                if heap.gc_threshold() > 0 {
105                    "Enabled"
106                } else {
107                    "Disabled"
108                }
109            );
110        }
111    }
112
113    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
114    // No explicit `set_root` calls are needed for them.
115    println!("\nRoot objects are held by variables:");
116    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
117
118    // Manually trigger garbage collection for partition1
119    println!("\nManually trigger garbage collection for partition1...");
120    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
121    println!("  Collected {} bytes", freed);
122
123    // Verify root objects are still valid
124    println!("\nVerify partition1 root objects are still valid:");
125    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
126    println!("  Object2: {}", unsafe { obj2.as_ref() });
127
128    // Manually trigger garbage collection for partition2
129    println!("\nManually trigger garbage collection for partition2...");
130    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
131    println!("  Collected {} bytes", freed);
132
133    // Verify partition2 root objects are still valid
134    println!("\nVerify partition2 root objects are still valid:");
135    println!("  Object4: '{}'", unsafe { obj4.as_ref() });
136
137    // Trigger garbage collection for partition1 again to collect unreferenced objects
138    println!("\nTrigger garbage collection for partition1 again...");
139    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
140    // to test collection. For this example, we'll just collect other garbage.
141    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  Collected {} bytes", freed);
143
144    // Verify remaining root objects are still valid
145    println!("\nVerify remaining root objects are still valid:");
146    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
147    println!("  Object2: {} (still a root)", unsafe { obj2.as_ref() });
148
149    // Demonstrate automatic garbage collection
150    println!("\nDemonstrate automatic garbage collection...");
151
152    // Create a small partition to demonstrate automatic GC
153    let small_partition = heap.create_partition(64 * 1024, 16 * 1024);
154
155    // Allocate multiple objects to fill partition
156    for i in 0..5 {
157        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
158            .map_err(|(err, _)| err)?;
159    }
160
161    println!("  Allocated 5 objects in small partition");
162
163    // Demonstrate weak references
164    println!("\nDemonstrate weak references:");
165    let weak_ref = heap.downgrade(&obj1);
166    println!("  Created weak reference: {:?}", weak_ref);
167
168    // Upgrade weak reference
169    match weak_ref.upgrade(&heap) {
170        Some(strong_ref) => {
171            println!("  Weak reference upgrade successful: '{}'", &*strong_ref);
172        }
173        None => {
174            println!("  Weak reference upgrade failed");
175        }
176    }
177
178    // Demonstrate complex types with GC references
179    println!("\nDemonstrate complex types with GC references:");
180    let mut node1 =
181        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
182    let mut node2 =
183        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
184
185    // Establish references between nodes
186    {
187        unsafe {
188            node1.with_write_barrier(&mut heap, |n| n.add_child(node2));
189        }
190        unsafe {
191            node2.with_write_barrier(&mut heap, |n| n.add_child(node1));
192        }
193    }
194
195    println!("  Created node1: {}", unsafe { node1.as_ref() });
196    println!("  Created node2: {}", unsafe { node2.as_ref() });
197
198    // Trigger garbage collection, verify circular references are handled correctly
199    println!("\nGarbage collection for handling circular references...");
200    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
201    println!("  回收了 {} 字节内存", freed);
202
203    // Demonstrate partition deletion
204    println!("\nDemonstrate partition deletion:");
205
206    // Create an empty partition
207    let empty_partition = heap.create_partition(64 * 1024, 16 * 1024);
208    println!("  Created empty partition: {:?}", empty_partition);
209
210    // Delete empty partition
211    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
212    println!("  Deleted empty partition successfully");
213
214    // Delete non-empty partition
215    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
216    println!("  Deleted non-empty partition successfully");
217
218    println!("\nExample completed!");
219    Ok(())
220}
Source

pub unsafe fn as_ptr(&self) -> NonNull<T>

Get a raw pointer to the GC-managed payload.

§Safety

The caller must ensure the GC object is still alive.

Source

pub unsafe fn downgrade(&self, heap: &mut GcHeap) -> GcWeak<T>

Create a weak reference from this GC reference.

§Safety

The caller must ensure the GC object is still alive.

Source

pub unsafe fn is_root(&self) -> bool

Check if this is a root object.

§Safety

The caller must ensure the GC object is still alive.

Source

pub fn node_ptr(&self) -> NonNull<GcHead>

Get node raw pointer (always safe — just returns the raw pointer value).

Examples found in repository?
examples/advanced_features.rs (line 323)
292fn 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    // Clean up
337    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
338    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
339
340    Ok(())
341}
Source

pub unsafe fn node_info(&self) -> &GcHead

Get node info (GC head metadata).

§Safety

The caller must ensure the GC object is still alive.

Trait Implementations§

Source§

impl<T: GcNode> Clone for GcRef<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: GcNode> Copy for GcRef<T>

Source§

impl<T: GcNode> Debug for GcRef<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: GcNode> Eq for GcRef<T>

Source§

impl<T: GcNode> From<&GcRef<T>> for NonNull<GcHead>

Source§

fn from(r: &GcRef<T>) -> Self

Converts to this type from the input type.
Source§

impl<T: GcNode> From<GcRef<T>> for NonNull<GcHead>

Source§

fn from(r: GcRef<T>) -> Self

Converts to this type from the input type.
Source§

impl<T: GcNode> PartialEq for GcRef<T>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl<T> !Send for GcRef<T>

§

impl<T> !Sync for GcRef<T>

§

impl<T> Freeze for GcRef<T>

§

impl<T> RefUnwindSafe for GcRef<T>
where T: RefUnwindSafe,

§

impl<T> Unpin for GcRef<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for GcRef<T>

§

impl<T> UnwindSafe for GcRef<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.