pub struct GcRef<T: GcNode> { /* private fields */ }Expand description
Garbage collection reference
Implementations§
Source§impl<T: GcNode> GcRef<T>
impl<T: GcNode> GcRef<T>
Sourcepub unsafe fn as_ref(&self) -> &T
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?
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
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 }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}Sourcepub unsafe fn try_from_ref(heap: &GcHeap, data_ref: &T) -> Option<Self>
pub unsafe fn try_from_ref(heap: &GcHeap, data_ref: &T) -> Option<Self>
Create GcRef
§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?
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}Sourcepub unsafe fn from_ref_unchecked(data_ref: &T) -> Self
pub unsafe fn from_ref_unchecked(data_ref: &T) -> Self
Unsafe conversion from &T to GcRef
§Safety
Caller must ensure &T comes from GcRef
Sourcepub unsafe fn with_write_barrier<F, R>(
&mut self,
heap: &mut GcHeap,
mutator: F,
) -> R
pub unsafe fn with_write_barrier<F, R>( &mut self, heap: &mut GcHeap, mutator: F, ) -> 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?
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
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}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}Sourcepub unsafe fn as_ptr(&self) -> NonNull<T>
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.
Sourcepub unsafe fn downgrade(&self, heap: &mut GcHeap) -> GcWeak<T>
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.
Sourcepub fn node_ptr(&self) -> NonNull<GcHead>
pub fn node_ptr(&self) -> NonNull<GcHead>
Get node raw pointer (always safe — just returns the raw pointer value).
Examples found in repository?
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}