Skip to main content

GcHeap

Struct GcHeap 

Source
pub struct GcHeap { /* private fields */ }

Implementations§

Source§

impl GcHeap

Source

pub const DUMMY_DISPOSE_CALLBACK: fn(&GcHeap, &GcHead)

Source

pub fn new(registry: &'static GcTypeRegistry) -> Self

Create a new garbage collection heap with an explicit GC type registry.

The heap starts with no partitions. Use create_partition to add partitions as needed.

Examples found in repository?
examples/advanced_features.rs (line 42)
41fn new_heap() -> GcHeap {
42    GcHeap::new(&GC_TYPE_REGISTRY)
43}
More examples
Hide additional examples
examples/gc_node_usage.rs (line 57)
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}
examples/performance_benchmark.rs (line 44)
38fn benchmark_object_sizes() {
39    let sizes = [10, 100, 500, 1000, 5000];
40
41    for &size in &sizes {
42        println!("\nTest object count: {}", size);
43
44        let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45        let partition = context.create_partition(64 * 1024, 16 * 1024);
46
47        // Measure allocation performance
48        let alloc_start = Instant::now();
49        let mut objects = Vec::new();
50        for _i in 0..size {
51            let node = unsafe {
52                context.alloc_raw(
53                    partition,
54                    SimpleNode {
55                        _data: vec![0u8; 100],
56                    },
57                )
58            } // Each node 100 bytes
59            .unwrap();
60            objects.push(node);
61        }
62        let alloc_duration = alloc_start.elapsed();
63
64        println!("  Allocated {} objects in: {:?}", size, alloc_duration);
65        println!(
66            "  Average allocation time per object: {:?}",
67            alloc_duration / size as u32
68        );
69
70        // Measure GC performance (all objects can be collected)
71        let gc_start = Instant::now();
72        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73        let gc_duration = gc_start.elapsed();
74
75        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76        println!(
77            "  Average collection time per byte: {:?}",
78            if freed > 0 {
79                gc_duration / freed as u32
80            } else {
81                Duration::from_nanos(0)
82            }
83        );
84    }
85}
86
87/// Test GC performance of complex object graphs
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}
154
155/// Test memory usage efficiency
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
examples/error_handling.rs (line 37)
34fn demonstrate_out_of_memory() -> GcResult<()> {
35    println!("1. Create limited memory partition...");
36
37    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38    context.set_memory_limit(2048); // 2KB global limit
39    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
40
41    // Allocate first large object (1KB + header)
42    println!("2. Allocate first large object...");
43    let gc1: GcRef<LargeData> =
44        match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45            Ok(gc_ref) => {
46                println!("  ✓ Successfully allocated first object (1KB)");
47                gc_ref
48            }
49            Err((error, _)) => {
50                println!("  ✗ First object allocation failed: {:?}", error);
51                return Ok(());
52            }
53        };
54
55    // Allocate second large object (1KB + header) - should exceed 2KB limit
56    println!("3. Try to allocate second large object...");
57    match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58        Err((GcError::PartitionFull, _)) => {
59            println!("  ✓ Correctly detected partition full error");
60        }
61        Ok(_) => {
62            println!("  ✗ Expected partition full error, but allocation succeeded");
63            return Ok(());
64        }
65        Err((other_error, _)) => {
66            println!(
67                "  ✗ Expected partition full error, but got: {:?}",
68                other_error
69            );
70            return Ok(());
71        }
72    }
73
74    // Clean up - through garbage collection instead of manual release
75    println!("  ✓ Automatic cleanup through GC");
76    context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78    Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149    println!("1. Test GC threshold API...");
150
151    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152    context.set_memory_limit(1024);
153    let _partition_id = context.create_partition(64 * 1024, 16 * 1024);
154
155    // Test default values
156    println!("2. Test default threshold...");
157    assert_eq!(context.gc_threshold(), 0);
158    println!("  ✓ Default threshold is 0, automatic GC disabled");
159
160    // Test setting threshold
161    println!("3. Test setting threshold...");
162    context.set_gc_threshold(512);
163    assert_eq!(context.gc_threshold(), 512);
164    println!("  ✓ Successfully set threshold to 512, automatic GC enabled");
165
166    // Test setting threshold exceeding memory limit
167    println!("4. Test setting threshold exceeding memory limit...");
168    context.set_gc_threshold(2048);
169    // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170    assert_eq!(context.gc_threshold(), 819);
171    println!(
172        "  ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173    );
174
175    // Test disabling automatic GC
176    println!("5. Test disabling automatic GC...");
177    context.set_gc_threshold(0);
178    assert_eq!(context.gc_threshold(), 0);
179    println!("  ✓ Successfully disabled automatic GC, threshold set to 0");
180
181    Ok(())
182}
examples/basic_usage.rs (line 51)
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 const fn opaque(&self) -> *mut u8

Source

pub const fn set_opaque(&mut self, opaque: *mut u8)

Source

pub fn memory_limit(&self) -> usize

Examples found in repository?
examples/performance_benchmark.rs (line 174)
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
More examples
Hide additional examples
examples/basic_usage.rs (line 89)
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 fn set_memory_limit(&mut self, limit: usize) -> usize

Examples found in repository?
examples/error_handling.rs (line 38)
34fn demonstrate_out_of_memory() -> GcResult<()> {
35    println!("1. Create limited memory partition...");
36
37    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38    context.set_memory_limit(2048); // 2KB global limit
39    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
40
41    // Allocate first large object (1KB + header)
42    println!("2. Allocate first large object...");
43    let gc1: GcRef<LargeData> =
44        match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45            Ok(gc_ref) => {
46                println!("  ✓ Successfully allocated first object (1KB)");
47                gc_ref
48            }
49            Err((error, _)) => {
50                println!("  ✗ First object allocation failed: {:?}", error);
51                return Ok(());
52            }
53        };
54
55    // Allocate second large object (1KB + header) - should exceed 2KB limit
56    println!("3. Try to allocate second large object...");
57    match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58        Err((GcError::PartitionFull, _)) => {
59            println!("  ✓ Correctly detected partition full error");
60        }
61        Ok(_) => {
62            println!("  ✗ Expected partition full error, but allocation succeeded");
63            return Ok(());
64        }
65        Err((other_error, _)) => {
66            println!(
67                "  ✗ Expected partition full error, but got: {:?}",
68                other_error
69            );
70            return Ok(());
71        }
72    }
73
74    // Clean up - through garbage collection instead of manual release
75    println!("  ✓ Automatic cleanup through GC");
76    context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78    Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149    println!("1. Test GC threshold API...");
150
151    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152    context.set_memory_limit(1024);
153    let _partition_id = context.create_partition(64 * 1024, 16 * 1024);
154
155    // Test default values
156    println!("2. Test default threshold...");
157    assert_eq!(context.gc_threshold(), 0);
158    println!("  ✓ Default threshold is 0, automatic GC disabled");
159
160    // Test setting threshold
161    println!("3. Test setting threshold...");
162    context.set_gc_threshold(512);
163    assert_eq!(context.gc_threshold(), 512);
164    println!("  ✓ Successfully set threshold to 512, automatic GC enabled");
165
166    // Test setting threshold exceeding memory limit
167    println!("4. Test setting threshold exceeding memory limit...");
168    context.set_gc_threshold(2048);
169    // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170    assert_eq!(context.gc_threshold(), 819);
171    println!(
172        "  ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173    );
174
175    // Test disabling automatic GC
176    println!("5. Test disabling automatic GC...");
177    context.set_gc_threshold(0);
178    assert_eq!(context.gc_threshold(), 0);
179    println!("  ✓ Successfully disabled automatic GC, threshold set to 0");
180
181    Ok(())
182}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 160)
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
Source

pub fn gc_threshold(&self) -> usize

Examples found in repository?
examples/error_handling.rs (line 157)
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149    println!("1. Test GC threshold API...");
150
151    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152    context.set_memory_limit(1024);
153    let _partition_id = context.create_partition(64 * 1024, 16 * 1024);
154
155    // Test default values
156    println!("2. Test default threshold...");
157    assert_eq!(context.gc_threshold(), 0);
158    println!("  ✓ Default threshold is 0, automatic GC disabled");
159
160    // Test setting threshold
161    println!("3. Test setting threshold...");
162    context.set_gc_threshold(512);
163    assert_eq!(context.gc_threshold(), 512);
164    println!("  ✓ Successfully set threshold to 512, automatic GC enabled");
165
166    // Test setting threshold exceeding memory limit
167    println!("4. Test setting threshold exceeding memory limit...");
168    context.set_gc_threshold(2048);
169    // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170    assert_eq!(context.gc_threshold(), 819);
171    println!(
172        "  ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173    );
174
175    // Test disabling automatic GC
176    println!("5. Test disabling automatic GC...");
177    context.set_gc_threshold(0);
178    assert_eq!(context.gc_threshold(), 0);
179    println!("  ✓ Successfully disabled automatic GC, threshold set to 0");
180
181    Ok(())
182}
More examples
Hide additional examples
examples/basic_usage.rs (line 104)
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 fn set_gc_threshold(&mut self, threshold: usize) -> usize

Examples found in repository?
examples/error_handling.rs (line 162)
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149    println!("1. Test GC threshold API...");
150
151    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152    context.set_memory_limit(1024);
153    let _partition_id = context.create_partition(64 * 1024, 16 * 1024);
154
155    // Test default values
156    println!("2. Test default threshold...");
157    assert_eq!(context.gc_threshold(), 0);
158    println!("  ✓ Default threshold is 0, automatic GC disabled");
159
160    // Test setting threshold
161    println!("3. Test setting threshold...");
162    context.set_gc_threshold(512);
163    assert_eq!(context.gc_threshold(), 512);
164    println!("  ✓ Successfully set threshold to 512, automatic GC enabled");
165
166    // Test setting threshold exceeding memory limit
167    println!("4. Test setting threshold exceeding memory limit...");
168    context.set_gc_threshold(2048);
169    // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170    assert_eq!(context.gc_threshold(), 819);
171    println!(
172        "  ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173    );
174
175    // Test disabling automatic GC
176    println!("5. Test disabling automatic GC...");
177    context.set_gc_threshold(0);
178    assert_eq!(context.gc_threshold(), 0);
179    println!("  ✓ Successfully disabled automatic GC, threshold set to 0");
180
181    Ok(())
182}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 224)
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
Source

pub fn should_gc(&self) -> bool

Check if garbage collection is needed

Source

pub fn set_root_node(&mut self, node: NonNull<GcHead>)

Source

pub fn contains(&self, node: NonNull<GcHead>) -> bool

Check if node was allocated in this heap

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 fn protect_node( &mut self, scope_stack_id: GcScopeStackId, node: NonNull<GcHead>, ) -> bool

Protect node from being gc collected.

  1. if node is local or root, it’s protected, returns true
  2. otherwise if has current scope, add node to current scope and returns true
  3. can’t protect, returns false
Source

pub fn protect_nodes_iter( &mut self, scope_stack_id: GcScopeStackId, nodes: impl Iterator<Item = NonNull<GcHead>>, )

Protect nodes from being gc collected, for each node do following steps:

  1. if node is local or root, do nothing
  2. if has current scope, add node to current scope
  3. can’t protect, returns false
Source

pub fn protect_nodes( &mut self, scope_stack_id: GcScopeStackId, nodes: &[NonNull<GcHead>], )

Protect nodes from being gc collected, for each node do following steps:

  1. if node is local or root, do nothing
  2. if has current scope, add node to current scope
  3. can’t protect, returns false
Source

pub const fn memory_used(&self) -> usize

Source§

impl GcHeap

Source

pub fn add_gray_node(&mut self, node: NonNull<GcHead>)

Source

pub fn mark_reset(&mut self, partition_id: GcPartitionId)

Source

pub fn mark_prepare(&mut self, partition_id: GcPartitionId)

Source

pub fn mark_grays( &mut self, partition_id: GcPartitionId, max_steps: usize, ) -> bool

Source

pub fn mark(&mut self, partition_id: GcPartitionId, max_steps: usize) -> bool

Source

pub fn sweep( &mut self, partition_id: GcPartitionId, on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize

dispose white nodes in the partition. on_dispose is called BEFORE a node will be disposed.

Source

pub fn garbage_collect( &mut self, partition_id: GcPartitionId, on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize

Collect garbage on given partition, call notify with node BEFORE it is disposed.

Examples found in repository?
examples/advanced_features.rs (line 103)
76fn 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    // Upgrade weak reference
91    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    // Try upgrading after releasing strong reference
102    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
115/// Demonstrate circular reference handling
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}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 72)
38fn benchmark_object_sizes() {
39    let sizes = [10, 100, 500, 1000, 5000];
40
41    for &size in &sizes {
42        println!("\nTest object count: {}", size);
43
44        let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45        let partition = context.create_partition(64 * 1024, 16 * 1024);
46
47        // Measure allocation performance
48        let alloc_start = Instant::now();
49        let mut objects = Vec::new();
50        for _i in 0..size {
51            let node = unsafe {
52                context.alloc_raw(
53                    partition,
54                    SimpleNode {
55                        _data: vec![0u8; 100],
56                    },
57                )
58            } // Each node 100 bytes
59            .unwrap();
60            objects.push(node);
61        }
62        let alloc_duration = alloc_start.elapsed();
63
64        println!("  Allocated {} objects in: {:?}", size, alloc_duration);
65        println!(
66            "  Average allocation time per object: {:?}",
67            alloc_duration / size as u32
68        );
69
70        // Measure GC performance (all objects can be collected)
71        let gc_start = Instant::now();
72        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73        let gc_duration = gc_start.elapsed();
74
75        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76        println!(
77            "  Average collection time per byte: {:?}",
78            if freed > 0 {
79                gc_duration / freed as u32
80            } else {
81                Duration::from_nanos(0)
82            }
83        );
84    }
85}
86
87/// Test GC performance of complex object graphs
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}
154
155/// Test memory usage efficiency
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
examples/error_handling.rs (line 76)
34fn demonstrate_out_of_memory() -> GcResult<()> {
35    println!("1. Create limited memory partition...");
36
37    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38    context.set_memory_limit(2048); // 2KB global limit
39    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
40
41    // Allocate first large object (1KB + header)
42    println!("2. Allocate first large object...");
43    let gc1: GcRef<LargeData> =
44        match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45            Ok(gc_ref) => {
46                println!("  ✓ Successfully allocated first object (1KB)");
47                gc_ref
48            }
49            Err((error, _)) => {
50                println!("  ✗ First object allocation failed: {:?}", error);
51                return Ok(());
52            }
53        };
54
55    // Allocate second large object (1KB + header) - should exceed 2KB limit
56    println!("3. Try to allocate second large object...");
57    match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58        Err((GcError::PartitionFull, _)) => {
59            println!("  ✓ Correctly detected partition full error");
60        }
61        Ok(_) => {
62            println!("  ✗ Expected partition full error, but allocation succeeded");
63            return Ok(());
64        }
65        Err((other_error, _)) => {
66            println!(
67                "  ✗ Expected partition full error, but got: {:?}",
68                other_error
69            );
70            return Ok(());
71        }
72    }
73
74    // Clean up - through garbage collection instead of manual release
75    println!("  ✓ Automatic cleanup through GC");
76    context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78    Ok(())
79}
examples/basic_usage.rs (line 120)
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§

impl GcHeap

Source

pub unsafe fn alloc_raw<T: GcNode>( &mut self, partition_id: GcPartitionId, payload: T, ) -> Result<GcRef<T>, (GcError, T)>

Allocate a typed gc node with payload data, do not put to any scope, even if the current scope is present.

§SAFETY

This function is unsafe because it directly manipulates raw pointers and memory allocation. The caller must ensure that the partition_id is valid and that the returned GcRef is properly managed to avoid memory leaks or use-after-free errors.

Examples found in repository?
examples/performance_benchmark.rs (lines 52-57)
38fn benchmark_object_sizes() {
39    let sizes = [10, 100, 500, 1000, 5000];
40
41    for &size in &sizes {
42        println!("\nTest object count: {}", size);
43
44        let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45        let partition = context.create_partition(64 * 1024, 16 * 1024);
46
47        // Measure allocation performance
48        let alloc_start = Instant::now();
49        let mut objects = Vec::new();
50        for _i in 0..size {
51            let node = unsafe {
52                context.alloc_raw(
53                    partition,
54                    SimpleNode {
55                        _data: vec![0u8; 100],
56                    },
57                )
58            } // Each node 100 bytes
59            .unwrap();
60            objects.push(node);
61        }
62        let alloc_duration = alloc_start.elapsed();
63
64        println!("  Allocated {} objects in: {:?}", size, alloc_duration);
65        println!(
66            "  Average allocation time per object: {:?}",
67            alloc_duration / size as u32
68        );
69
70        // Measure GC performance (all objects can be collected)
71        let gc_start = Instant::now();
72        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73        let gc_duration = gc_start.elapsed();
74
75        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76        println!(
77            "  Average collection time per byte: {:?}",
78            if freed > 0 {
79                gc_duration / freed as u32
80            } else {
81                Duration::from_nanos(0)
82            }
83        );
84    }
85}
86
87/// Test GC performance of complex object graphs
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}
154
155/// Test memory usage efficiency
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
More examples
Hide additional examples
examples/error_handling.rs (line 44)
34fn demonstrate_out_of_memory() -> GcResult<()> {
35    println!("1. Create limited memory partition...");
36
37    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38    context.set_memory_limit(2048); // 2KB global limit
39    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
40
41    // Allocate first large object (1KB + header)
42    println!("2. Allocate first large object...");
43    let gc1: GcRef<LargeData> =
44        match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45            Ok(gc_ref) => {
46                println!("  ✓ Successfully allocated first object (1KB)");
47                gc_ref
48            }
49            Err((error, _)) => {
50                println!("  ✗ First object allocation failed: {:?}", error);
51                return Ok(());
52            }
53        };
54
55    // Allocate second large object (1KB + header) - should exceed 2KB limit
56    println!("3. Try to allocate second large object...");
57    match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58        Err((GcError::PartitionFull, _)) => {
59            println!("  ✓ Correctly detected partition full error");
60        }
61        Ok(_) => {
62            println!("  ✗ Expected partition full error, but allocation succeeded");
63            return Ok(());
64        }
65        Err((other_error, _)) => {
66            println!(
67                "  ✗ Expected partition full error, but got: {:?}",
68                other_error
69            );
70            return Ok(());
71        }
72    }
73
74    // Clean up - through garbage collection instead of manual release
75    println!("  ✓ Automatic cleanup through GC");
76    context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78    Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
examples/advanced_features.rs (line 179)
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}
examples/basic_usage.rs (line 66)
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 alloc_root_raw<T: GcNode>( &mut self, partition_id: GcPartitionId, payload: T, ) -> Result<GcRef<T>, (GcError, T)>

Allocate a root node — bypasses arena directly to system malloc.

Root nodes are permanent and should not waste arena space.

§SAFETY

This function is unsafe because it directly manipulates raw pointers and memory allocation. The caller must ensure that the partition_id is valid and that the returned GcRef is properly managed to avoid memory leaks or use-after-free errors.

Examples found in repository?
examples/advanced_features.rs (line 83)
76fn 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    // Upgrade weak reference
91    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    // Try upgrading after releasing strong reference
102    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
115/// Demonstrate circular reference handling
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}
Source§

impl GcHeap

Source

pub fn bind(&mut self, master: NonNull<GcHead>, slave: NonNull<GcHead>)

Establishes a directed reference from master to slave and performs the necessary write barrier for tri-color incremental GC.

§When to use

Call this whenever a GC node (master) starts referencing another GC node (slave) through a pointer write, e.g.:

  • Setting an object property to an object/string value
  • Pushing an element into an array
  • Storing a result value into a Promise
  • Updating a closure variable reference
§Write barrier semantics

In tri-color marking, if master is already Black (fully traced) and slave is White (not yet traced), the slave would be incorrectly swept as garbage. This method prevents that by:

  1. Checking the colors of master and slave.
  2. If master is Black and slave is White/Gray, marking slave as Gray and enqueuing it into the gray list of its partition, ensuring it will be traced in the current GC cycle.
§Safety

Both pointers must point to valid, live GC nodes managed by this heap.

Source§

impl GcHeap

Source

pub fn nodes(&self, partition_id: GcPartitionId) -> NodeLinkIter<'_>

Source§

impl GcHeap

Source

pub fn create_partition( &mut self, arena_capacity: usize, arena_max_alloc: usize, ) -> GcPartitionId

Create a new partition and return its ID.

§Parameters
  • arena_capacity: arena size in bytes. 0 = disable arena for this partition.
  • arena_max_alloc: allocations larger than this skip the arena.
Examples found in repository?
examples/gc_node_usage.rs (line 58)
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 49)
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    // Demonstrate weak reference functionality
52    println!("\n=== Weak reference functionality demonstration ===");
53    demonstrate_weak_references(&mut heap, partition)?;
54
55    // Demonstrate circular reference handling
56    println!("\n=== Circular reference handling demonstration ===");
57    demonstrate_cyclic_references(&mut heap, partition)?;
58
59    // Demonstrate complex data structures
60    println!("\n=== Complex data structures demonstration ===");
61    demonstrate_complex_structures(&mut heap, partition)?;
62
63    // Demonstrate reference recovery functionality
64    println!("\n=== Reference recovery functionality demonstration ===");
65    demonstrate_reference_recovery(&mut heap, partition)?;
66
67    // Demonstrate cross-context detection
68    println!("\n=== Cross-context detection demonstration ===");
69    demonstrate_cross_context_detection()?;
70
71    println!("\nAll advanced feature demonstrations completed!");
72    Ok(())
73}
74
75/// Demonstrate weak reference functionality
76fn 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    // Upgrade weak reference
91    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    // Try upgrading after releasing strong reference
102    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
115/// Demonstrate circular reference handling
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}
examples/performance_benchmark.rs (line 45)
38fn benchmark_object_sizes() {
39    let sizes = [10, 100, 500, 1000, 5000];
40
41    for &size in &sizes {
42        println!("\nTest object count: {}", size);
43
44        let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45        let partition = context.create_partition(64 * 1024, 16 * 1024);
46
47        // Measure allocation performance
48        let alloc_start = Instant::now();
49        let mut objects = Vec::new();
50        for _i in 0..size {
51            let node = unsafe {
52                context.alloc_raw(
53                    partition,
54                    SimpleNode {
55                        _data: vec![0u8; 100],
56                    },
57                )
58            } // Each node 100 bytes
59            .unwrap();
60            objects.push(node);
61        }
62        let alloc_duration = alloc_start.elapsed();
63
64        println!("  Allocated {} objects in: {:?}", size, alloc_duration);
65        println!(
66            "  Average allocation time per object: {:?}",
67            alloc_duration / size as u32
68        );
69
70        // Measure GC performance (all objects can be collected)
71        let gc_start = Instant::now();
72        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73        let gc_duration = gc_start.elapsed();
74
75        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76        println!(
77            "  Average collection time per byte: {:?}",
78            if freed > 0 {
79                gc_duration / freed as u32
80            } else {
81                Duration::from_nanos(0)
82            }
83        );
84    }
85}
86
87/// Test GC performance of complex object graphs
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}
154
155/// Test memory usage efficiency
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
examples/error_handling.rs (line 39)
34fn demonstrate_out_of_memory() -> GcResult<()> {
35    println!("1. Create limited memory partition...");
36
37    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38    context.set_memory_limit(2048); // 2KB global limit
39    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
40
41    // Allocate first large object (1KB + header)
42    println!("2. Allocate first large object...");
43    let gc1: GcRef<LargeData> =
44        match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45            Ok(gc_ref) => {
46                println!("  ✓ Successfully allocated first object (1KB)");
47                gc_ref
48            }
49            Err((error, _)) => {
50                println!("  ✗ First object allocation failed: {:?}", error);
51                return Ok(());
52            }
53        };
54
55    // Allocate second large object (1KB + header) - should exceed 2KB limit
56    println!("3. Try to allocate second large object...");
57    match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58        Err((GcError::PartitionFull, _)) => {
59            println!("  ✓ Correctly detected partition full error");
60        }
61        Ok(_) => {
62            println!("  ✗ Expected partition full error, but allocation succeeded");
63            return Ok(());
64        }
65        Err((other_error, _)) => {
66            println!(
67                "  ✗ Expected partition full error, but got: {:?}",
68                other_error
69            );
70            return Ok(());
71        }
72    }
73
74    // Clean up - through garbage collection instead of manual release
75    println!("  ✓ Automatic cleanup through GC");
76    context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78    Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149    println!("1. Test GC threshold API...");
150
151    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152    context.set_memory_limit(1024);
153    let _partition_id = context.create_partition(64 * 1024, 16 * 1024);
154
155    // Test default values
156    println!("2. Test default threshold...");
157    assert_eq!(context.gc_threshold(), 0);
158    println!("  ✓ Default threshold is 0, automatic GC disabled");
159
160    // Test setting threshold
161    println!("3. Test setting threshold...");
162    context.set_gc_threshold(512);
163    assert_eq!(context.gc_threshold(), 512);
164    println!("  ✓ Successfully set threshold to 512, automatic GC enabled");
165
166    // Test setting threshold exceeding memory limit
167    println!("4. Test setting threshold exceeding memory limit...");
168    context.set_gc_threshold(2048);
169    // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170    assert_eq!(context.gc_threshold(), 819);
171    println!(
172        "  ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173    );
174
175    // Test disabling automatic GC
176    println!("5. Test disabling automatic GC...");
177    context.set_gc_threshold(0);
178    assert_eq!(context.gc_threshold(), 0);
179    println!("  ✓ Successfully disabled automatic GC, threshold set to 0");
180
181    Ok(())
182}
examples/basic_usage.rs (line 58)
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 fn finalize_partition( &self, partition_id: GcPartitionId, ) -> Option<GcNodeLink>

Phase 1: Finalize — call Drop on all node payloads without freeing memory.

Only takes &self, so Drop implementations can safely access GcHeap via a shared reference. Returns the node link containing all finalized nodes, which must be passed to [dealloc_partition] to reclaim memory.

Scope caches associated with this partition are cleared before any drops are called, so that GcScopeState::clear() (which only touches node flags) runs before payload drops.

Source

pub fn dealloc_partition( &mut self, partition_id: GcPartitionId, link: GcNodeLink, ) -> usize

Phase 2: Dealloc — free memory of all finalized nodes and reset the partition.

Takes &mut self — no Drop callbacks run at this point, so there is no risk of reentrant &mut self access. The link must be the value returned by [finalize_partition] for the same partition.

Returns the total number of bytes freed.

Source

pub fn remove_partition( &mut self, partition_id: GcPartitionId, _on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize

👎Deprecated:

unsound — use finalize_partition(&self) + dealloc_partition(&mut self) instead

Remove a partition and reclaim all its memory.

⚠️ DEPRECATED — This method is inherently unsound. It holds &mut self while Drop callbacks run inside [finalize_partition], and those callbacks can re-enter GcHeap through raw pointers, creating aliasing &mut references (UB).

Use the two-phase API instead:

let link = gc_heap.finalize_partition(pid);
// ... (Drop callbacks that access GcHeap are safe here) ...
if let Some(link) = link {
    gc_heap.dealloc_partition(pid, link);
}

See [finalize_partition] (takes &self) and [dealloc_partition] (takes &mut self) for details.

The on_dispose parameter is kept for API compatibility but is no longer called — Drop is handled internally by finalize_partition.

Examples found in repository?
examples/error_handling.rs (line 121)
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
More examples
Hide additional examples
examples/basic_usage.rs (line 211)
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 fn partition(&self, partition_id: GcPartitionId) -> Option<&GcPartition>

Get partition information

Examples found in repository?
examples/performance_benchmark.rs (line 172)
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
More examples
Hide additional examples
examples/error_handling.rs (line 113)
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83    println!("1. Test non-existent partition operations...");
84
85    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86    let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88    // Test allocating objects in non-existent partition
89    match unsafe {
90        context.alloc_raw(
91            invalid_partition,
92            TestData {
93                value: 42,
94                name: "test".to_string(),
95            },
96        )
97    } {
98        Err((GcError::PartitionNotFound, _)) => {
99            println!("  ✓ Allocating objects in non-existent partition returns correct error");
100        }
101        Ok(_) => {
102            println!("  ✗ Expected partition not found error, but allocation succeeded");
103        }
104        Err((other_error, _)) => {
105            println!(
106                "  ✗ Expected partition not found error, but got: {:?}",
107                other_error
108            );
109        }
110    }
111
112    // Test getting non-existent partition information
113    let partition_info = context.partition(invalid_partition);
114    assert!(
115        partition_info.is_none(),
116        "Non-existent partition should return None"
117    );
118    println!("  ✓ Getting non-existent partition info returns None");
119
120    // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121    context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122    println!("  ✓ Removing non-existent partition silently fails");
123
124    println!("\n2. Test non-empty partition deletion...");
125    let partition_id = context.create_partition(64 * 1024, 16 * 1024);
126
127    // Allocate objects in partition
128    let obj = unsafe {
129        context.alloc_raw(
130            partition_id,
131            TestData {
132                value: 1,
133                name: "obj".to_string(),
134            },
135        )
136    }
137    .unwrap();
138    let _ = obj;
139
140    // Try to delete non-empty partition (remove_partition will force cleanup)
141    context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144    Ok(())
145}
examples/basic_usage.rs (line 88)
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 fn partition_mut( &mut self, partition_id: GcPartitionId, ) -> Option<&mut GcPartition>

Get partition information

Source

pub fn partition_ids(&self) -> Vec<GcPartitionId>

Get all partition IDs

Examples found in repository?
examples/basic_usage.rs (line 54)
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§

impl GcHeap

Source

pub fn acquire_scope_stack(&mut self, par: GcPartitionId) -> GcScopeStackId

find an idle scope stack, or create a new if none available

Examples found in repository?
examples/gc_node_usage.rs (line 59)
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}
Source

pub fn release_scope_stack(&mut self, stack_id: GcScopeStackId)

Examples found in repository?
examples/gc_node_usage.rs (line 70)
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}
Source

pub fn scope_max_depth(&self, stack_id: GcScopeStackId) -> u32

get max depth of a scope stack

Source

pub fn scope( &self, stack_id: GcScopeStackId, depth: u32, ) -> Option<&GcScopeState<'_>>

get scope state specified by (stack_id, depth). where depth is 1-based (1 means index #0)

Source

pub unsafe fn scope_unchecked( &self, stack_id: GcScopeStackId, index: u32, ) -> &GcScopeState<'_>

Get scope state by 0-based index without bounds check.

§Safety

Caller must ensure index < scope_max_depth(stack_id).

Source

pub fn new_scope<'s>(&'s mut self, stack_id: GcScopeStackId) -> GcScope<'s>

push a new scope on the stack, returns new scope’s handle. the scope will be automatically popped when this handle is dropped.

§Panics

Panics if an earlier handle is dropped while a later handle is still alive (LIFO order violation is enforced at runtime).

Source

pub fn current_scope( &self, stack_id: GcScopeStackId, ) -> Option<&GcScopeState<'_>>

get last (top-most) scope from the stack

Source

pub fn with_current_scope_of<R>( &mut self, stack_id: GcScopeStackId, f: impl FnOnce(&mut GcScopeState<'_>) -> R, ) -> Option<R>

run closure with last (top-most) scope from the stack

Source

pub fn with_new_scope<R>( &mut self, stack_id: GcScopeStackId, f: impl FnOnce(GcScope<'_>) -> R, ) -> R

Examples found in repository?
examples/gc_node_usage.rs (lines 31-38)
26fn alloc_static(
27    heap: &mut GcHeap,
28    stack_id: GcScopeStackId,
29    value: i32,
30) -> GcResult<GcRef<StaticNode>> {
31    heap.with_new_scope(stack_id, |ctx| {
32        let r = ctx
33            .alloc_local(StaticNode { _value: value })
34            .map_err(|(err, _)| err)
35            .map(|gc| gc.into_raw());
36        ctx.clear();
37        r
38    })
39}
40
41fn alloc_other(
42    heap: &mut GcHeap,
43    stack_id: GcScopeStackId,
44    value: i32,
45) -> GcResult<GcRef<OtherNode>> {
46    heap.with_new_scope(stack_id, |ctx| {
47        let r = ctx
48            .alloc_local(OtherNode { _value: value })
49            .map_err(|(err, _)| err)
50            .map(|gc| gc.into_raw());
51        ctx.clear();
52        r
53    })
54}
Source§

impl GcHeap

Source

pub fn create_trace_ctx(&self, cap: usize) -> GcTraceCtx<'_>

Source

pub fn trace_node(&self, node: NonNull<GcHead>, gcx: &mut GcTraceCtx<'_>)

Trace direct children of a node into the given trace context

Source

pub fn traverse_start(&mut self, partition_id: GcPartitionId)

Source

pub fn traverse( &mut self, node: NonNull<GcHead>, filter: Option<GcPartitionId>, callback: impl FnMut(NonNull<GcHead>, Option<NonNull<GcHead>>), )

Traverses the node tree starting at node in depth-first order, invoking callback on each visited node with its optional parent. If filter is Some, only nodes in the specified partition are visited.

Source§

impl GcHeap

Source

pub fn downgrade<T: GcNode>(&mut self, gc_ref: &GcRef<T>) -> GcWeak<T>

Create weak reference.

Examples found in repository?
examples/advanced_features.rs (line 86)
76fn 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    // Upgrade weak reference
91    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    // Try upgrading after releasing strong reference
102    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}
More examples
Hide additional examples
examples/basic_usage.rs (line 165)
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 fn upgrade<'a, T: GcNode>( &'a self, weak_ref: &GcWeak<T>, ) -> Option<Gc<'a, T>>

Upgrade weak reference

Trait Implementations§

Source§

impl Drop for GcHeap

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for GcHeap

§

impl !Send for GcHeap

§

impl !Sync for GcHeap

§

impl !UnwindSafe for GcHeap

§

impl Freeze for GcHeap

§

impl Unpin for GcHeap

§

impl UnsafeUnpin for GcHeap

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> 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, 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.