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

Examples found in repository?
examples/advanced_features.rs (line 44)
43fn new_heap() -> GcHeap {
44    GcHeap::new(&GC_TYPE_REGISTRY)
45}
More examples
Hide additional examples
examples/gc_node_usage.rs (line 52)
51fn main() -> GcResult<()> {
52    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
53    let scope = heap.create_partition();
54
55    let static_ref = alloc_static(&mut heap, scope, 10)?;
56    let other_ref = alloc_other(&mut heap, scope, 20)?;
57
58    println!("Static node value: {}", static_ref._value);
59    println!("Other node value: {}", other_ref._value);
60
61    println!("gc_node_usage example verified");
62
63    Ok(())
64}
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();
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();
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                        nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123                    }
124                }
125                // Every 10 nodes form a cycle
126                if i % 10 == 0 && i + 9 < size {
127                    let n = nodes[i];
128                    nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129                }
130            }
131        }
132        let graph_duration = graph_start.elapsed();
133
134        println!("  Built complex object graph in: {:?}", graph_duration);
135
136        // Measure GC performance
137        let gc_start = Instant::now();
138        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139        let gc_duration = gc_start.elapsed();
140
141        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142        println!(
143            "  Object graph complexity: average {} neighbors per node",
144            if size > 0 { (size * 5) / size } else { 0 }
145        );
146    }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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();
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();
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 53)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
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 168)
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
More examples
Hide additional examples
examples/basic_usage.rs (line 91)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
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();
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();
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();
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 154)
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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 106)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
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();
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 218)
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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 305)
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275    println!("1. Create two independent heaps...");
276
277    let mut heap1 = new_heap();
278    let mut heap2 = new_heap();
279
280    let partition1 = heap1.create_partition();
281    let partition2 = heap2.create_partition();
282
283    let obj1 = unsafe {
284        heap1.alloc_root_raw(
285            partition1,
286            TestData {
287                value: 1,
288                name: "obj1".to_string(),
289            },
290        )
291    }
292    .map_err(|(e, _)| e)?;
293    let obj2 = unsafe {
294        heap2.alloc_raw(
295            partition2,
296            TestData {
297                value: 2,
298                name: "obj2".to_string(),
299            },
300        )
301    }
302    .map_err(|(e, _)| e)?;
303
304    println!("2. Test object source detection...");
305    assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306    assert!(
307        !heap1.contains(obj2.node_ptr()),
308        "obj2 should not be from heap1"
309    );
310    assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311    assert!(
312        !heap2.contains(obj1.node_ptr()),
313        "obj1 should not be from heap2"
314    );
315
316    println!("  ✓ Cross-context detection correct");
317
318    // Clean up
319    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322    Ok(())
323}
Source

pub fn protect_node(&mut self, 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, 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, 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)

ensure marking is in progress, if marking is in progress, exit do nothing; if marking cycle is not started, start new cycle.

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

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 105)
78fn demonstrate_weak_references(
79    heap: &mut GcHeap,
80    partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82    println!("1. Create strong and weak references...");
83
84    let strong_ref =
85        unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86            .map_err(|(err, _)| err)?;
87
88    let weak_ref = heap.downgrade(&strong_ref);
89    println!("  Created strong reference: {:?}", strong_ref);
90    println!("  Created weak reference: {:?}", weak_ref);
91
92    // Upgrade weak reference
93    println!("\n2. Upgrade weak reference...");
94    match weak_ref.upgrade(heap) {
95        Some(upgraded) => {
96            let data = upgraded.deref();
97            println!("  Weak reference upgrade successful: '{}'", data);
98            assert_eq!(data, "Strong Reference Data");
99        }
100        None => println!("  Weak reference upgrade failed"),
101    }
102
103    // Try upgrading after releasing strong reference
104    println!("\n3. Upgrade weak reference after releasing strong reference...");
105    heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107    match weak_ref.upgrade(heap) {
108        Some(_) => {
109            println!("  Weak reference can still be upgraded (object may still be in memory)")
110        }
111        None => println!("  Weak reference upgrade failed (object has been collected)"),
112    }
113
114    Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119    heap: &mut GcHeap,
120    partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122    println!("1. Create circular reference nodes...");
123
124    // Create two mutually referencing nodes
125    let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126        .map_err(|(err, _)| err)?;
127    let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128        .map_err(|(err, _)| err)?;
129
130    // Establish circular references
131    {
132        node1.with_mut(heap, |n| n.set_partner(node2));
133        node2.with_mut(heap, |n| n.set_partner(node1));
134    }
135
136    println!("  Created node1: {}", node1.deref());
137    println!("  Created node2: {}", node2.deref());
138
139    // Trigger garbage collection
140    println!("\n2. Trigger garbage collection (circular references still exist)...");
141    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  回收了 {} 字节内存", freed);
143
144    // Verify circular references still exist
145    println!("\n3. Verify circular references...");
146    println!("  Node1's partner: {}", node1.get_partner_name());
147    println!("  Node2's partner: {}", node2.get_partner_name());
148
149    // Clear root object status, let circular references be collected
150    println!("\n4. Clear root object status and trigger GC again...");
151    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152    println!(
153        "  Freed {} bytes of memory (circular references correctly collected)",
154        freed
155    );
156
157    Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162    heap: &mut GcHeap,
163    partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165    println!("1. Create complex data structures...");
166
167    // Create multiple nodes
168    let mut root_node =
169        unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170    let mut child1 =
171        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172    let child2 =
173        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174    let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175        .map_err(|(err, _)| err)?;
176
177    // Build tree structure
178    {
179        root_node.with_mut(heap, |n| n.add_child(child1));
180        root_node.with_mut(heap, |n| n.add_child(child2));
181        child1.with_mut(heap, |n| n.add_child(grandchild));
182    }
183
184    // Create data container
185    let container = unsafe {
186        heap.alloc_root_raw(
187            partition,
188            DataContainer {
189                root: root_node,
190                metadata: vec![1, 2, 3],
191                optional_data: Some(child1),
192            },
193        )
194    }
195    .map_err(|(err, _)| err)?;
196
197    println!("  Created tree structure:");
198    println!("    Root -> Child 1 -> Grandchild");
199    println!("    Root -> Child 2");
200    println!("  Created data container");
201
202    // Trigger garbage collection
203    println!("\n2. Trigger garbage collection...");
204    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205    println!("  回收了 {} 字节内存", freed);
206
207    // Verify data structure integrity
208    println!("\n3. Verify data structure integrity...");
209    {
210        println!("  Container root node: {}", container.root.name);
211        println!("  Metadata length: {}", container.metadata.len());
212        println!(
213            "  Optional data exists: {}",
214            container.optional_data.is_some()
215        );
216    }
217
218    Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223    heap: &mut GcHeap,
224    partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226    println!("1. Create object and get reference...");
227
228    let original_ref = unsafe {
229        heap.alloc_raw(
230            partition,
231            TestData {
232                value: 42,
233                name: "test".to_string(),
234            },
235        )
236    }
237    .map_err(|(err, _)| err)?;
238
239    let data_ref = original_ref.deref();
240    println!("  Original reference: {:?}", original_ref);
241    println!("  Data: {:?}", data_ref);
242
243    // Recover GcRef from reference
244    println!("\n2. Recover GcRef from reference...");
245    let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247    match recovered_ref {
248        Some(recovered) => {
249            println!("  Recovery successful: {:?}", recovered);
250            let recovered_data = recovered.deref();
251            println!("  Recovered data: {:?}", recovered_data);
252            println!("  Data equal: {}", data_ref == recovered_data);
253            println!("  Reference equal: {}", original_ref == recovered);
254        }
255        None => println!("  Recovery failed (possibly type registration issue)"),
256    }
257
258    // Test invalid reference recovery - create an object not in GC heap
259    println!("\n3. Test invalid reference recovery...");
260    let local_data = TestData {
261        value: 100,
262        name: "local".to_string(),
263    };
264    let invalid_result = GcRef::try_from_ref(heap, &local_data);
265    println!(
266        "  Invalid reference recovery result: {:?} (should be None)",
267        invalid_result
268    );
269
270    Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275    println!("1. Create two independent heaps...");
276
277    let mut heap1 = new_heap();
278    let mut heap2 = new_heap();
279
280    let partition1 = heap1.create_partition();
281    let partition2 = heap2.create_partition();
282
283    let obj1 = unsafe {
284        heap1.alloc_root_raw(
285            partition1,
286            TestData {
287                value: 1,
288                name: "obj1".to_string(),
289            },
290        )
291    }
292    .map_err(|(e, _)| e)?;
293    let obj2 = unsafe {
294        heap2.alloc_raw(
295            partition2,
296            TestData {
297                value: 2,
298                name: "obj2".to_string(),
299            },
300        )
301    }
302    .map_err(|(e, _)| e)?;
303
304    println!("2. Test object source detection...");
305    assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306    assert!(
307        !heap1.contains(obj2.node_ptr()),
308        "obj2 should not be from heap1"
309    );
310    assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311    assert!(
312        !heap2.contains(obj1.node_ptr()),
313        "obj1 should not be from heap2"
314    );
315
316    println!("  ✓ Cross-context detection correct");
317
318    // Clean up
319    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322    Ok(())
323}
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();
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();
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                        nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123                    }
124                }
125                // Every 10 nodes form a cycle
126                if i % 10 == 0 && i + 9 < size {
127                    let n = nodes[i];
128                    nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129                }
130            }
131        }
132        let graph_duration = graph_start.elapsed();
133
134        println!("  Built complex object graph in: {:?}", graph_duration);
135
136        // Measure GC performance
137        let gc_start = Instant::now();
138        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139        let gc_duration = gc_start.elapsed();
140
141        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142        println!(
143            "  Object graph complexity: average {} neighbors per node",
144            if size > 0 { (size * 5) / size } else { 0 }
145        );
146    }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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 122)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
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();
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();
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                        nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123                    }
124                }
125                // Every 10 nodes form a cycle
126                if i % 10 == 0 && i + 9 < size {
127                    let n = nodes[i];
128                    nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129                }
130            }
131        }
132        let graph_duration = graph_start.elapsed();
133
134        println!("  Built complex object graph in: {:?}", graph_duration);
135
136        // Measure GC performance
137        let gc_start = Instant::now();
138        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139        let gc_duration = gc_start.elapsed();
140
141        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142        println!(
143            "  Object graph complexity: average {} neighbors per node",
144            if size > 0 { (size * 5) / size } else { 0 }
145        );
146    }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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();
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 171)
161fn demonstrate_complex_structures(
162    heap: &mut GcHeap,
163    partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165    println!("1. Create complex data structures...");
166
167    // Create multiple nodes
168    let mut root_node =
169        unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170    let mut child1 =
171        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172    let child2 =
173        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174    let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175        .map_err(|(err, _)| err)?;
176
177    // Build tree structure
178    {
179        root_node.with_mut(heap, |n| n.add_child(child1));
180        root_node.with_mut(heap, |n| n.add_child(child2));
181        child1.with_mut(heap, |n| n.add_child(grandchild));
182    }
183
184    // Create data container
185    let container = unsafe {
186        heap.alloc_root_raw(
187            partition,
188            DataContainer {
189                root: root_node,
190                metadata: vec![1, 2, 3],
191                optional_data: Some(child1),
192            },
193        )
194    }
195    .map_err(|(err, _)| err)?;
196
197    println!("  Created tree structure:");
198    println!("    Root -> Child 1 -> Grandchild");
199    println!("    Root -> Child 2");
200    println!("  Created data container");
201
202    // Trigger garbage collection
203    println!("\n2. Trigger garbage collection...");
204    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205    println!("  回收了 {} 字节内存", freed);
206
207    // Verify data structure integrity
208    println!("\n3. Verify data structure integrity...");
209    {
210        println!("  Container root node: {}", container.root.name);
211        println!("  Metadata length: {}", container.metadata.len());
212        println!(
213            "  Optional data exists: {}",
214            container.optional_data.is_some()
215        );
216    }
217
218    Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223    heap: &mut GcHeap,
224    partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226    println!("1. Create object and get reference...");
227
228    let original_ref = unsafe {
229        heap.alloc_raw(
230            partition,
231            TestData {
232                value: 42,
233                name: "test".to_string(),
234            },
235        )
236    }
237    .map_err(|(err, _)| err)?;
238
239    let data_ref = original_ref.deref();
240    println!("  Original reference: {:?}", original_ref);
241    println!("  Data: {:?}", data_ref);
242
243    // Recover GcRef from reference
244    println!("\n2. Recover GcRef from reference...");
245    let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247    match recovered_ref {
248        Some(recovered) => {
249            println!("  Recovery successful: {:?}", recovered);
250            let recovered_data = recovered.deref();
251            println!("  Recovered data: {:?}", recovered_data);
252            println!("  Data equal: {}", data_ref == recovered_data);
253            println!("  Reference equal: {}", original_ref == recovered);
254        }
255        None => println!("  Recovery failed (possibly type registration issue)"),
256    }
257
258    // Test invalid reference recovery - create an object not in GC heap
259    println!("\n3. Test invalid reference recovery...");
260    let local_data = TestData {
261        value: 100,
262        name: "local".to_string(),
263    };
264    let invalid_result = GcRef::try_from_ref(heap, &local_data);
265    println!(
266        "  Invalid reference recovery result: {:?} (should be None)",
267        invalid_result
268    );
269
270    Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275    println!("1. Create two independent heaps...");
276
277    let mut heap1 = new_heap();
278    let mut heap2 = new_heap();
279
280    let partition1 = heap1.create_partition();
281    let partition2 = heap2.create_partition();
282
283    let obj1 = unsafe {
284        heap1.alloc_root_raw(
285            partition1,
286            TestData {
287                value: 1,
288                name: "obj1".to_string(),
289            },
290        )
291    }
292    .map_err(|(e, _)| e)?;
293    let obj2 = unsafe {
294        heap2.alloc_raw(
295            partition2,
296            TestData {
297                value: 2,
298                name: "obj2".to_string(),
299            },
300        )
301    }
302    .map_err(|(e, _)| e)?;
303
304    println!("2. Test object source detection...");
305    assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306    assert!(
307        !heap1.contains(obj2.node_ptr()),
308        "obj2 should not be from heap1"
309    );
310    assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311    assert!(
312        !heap2.contains(obj1.node_ptr()),
313        "obj1 should not be from heap2"
314    );
315
316    println!("  ✓ Cross-context detection correct");
317
318    // Clean up
319    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322    Ok(())
323}
examples/basic_usage.rs (line 68)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
Source

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

§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 85)
78fn demonstrate_weak_references(
79    heap: &mut GcHeap,
80    partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82    println!("1. Create strong and weak references...");
83
84    let strong_ref =
85        unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86            .map_err(|(err, _)| err)?;
87
88    let weak_ref = heap.downgrade(&strong_ref);
89    println!("  Created strong reference: {:?}", strong_ref);
90    println!("  Created weak reference: {:?}", weak_ref);
91
92    // Upgrade weak reference
93    println!("\n2. Upgrade weak reference...");
94    match weak_ref.upgrade(heap) {
95        Some(upgraded) => {
96            let data = upgraded.deref();
97            println!("  Weak reference upgrade successful: '{}'", data);
98            assert_eq!(data, "Strong Reference Data");
99        }
100        None => println!("  Weak reference upgrade failed"),
101    }
102
103    // Try upgrading after releasing strong reference
104    println!("\n3. Upgrade weak reference after releasing strong reference...");
105    heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107    match weak_ref.upgrade(heap) {
108        Some(_) => {
109            println!("  Weak reference can still be upgraded (object may still be in memory)")
110        }
111        None => println!("  Weak reference upgrade failed (object has been collected)"),
112    }
113
114    Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119    heap: &mut GcHeap,
120    partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122    println!("1. Create circular reference nodes...");
123
124    // Create two mutually referencing nodes
125    let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126        .map_err(|(err, _)| err)?;
127    let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128        .map_err(|(err, _)| err)?;
129
130    // Establish circular references
131    {
132        node1.with_mut(heap, |n| n.set_partner(node2));
133        node2.with_mut(heap, |n| n.set_partner(node1));
134    }
135
136    println!("  Created node1: {}", node1.deref());
137    println!("  Created node2: {}", node2.deref());
138
139    // Trigger garbage collection
140    println!("\n2. Trigger garbage collection (circular references still exist)...");
141    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  回收了 {} 字节内存", freed);
143
144    // Verify circular references still exist
145    println!("\n3. Verify circular references...");
146    println!("  Node1's partner: {}", node1.get_partner_name());
147    println!("  Node2's partner: {}", node2.get_partner_name());
148
149    // Clear root object status, let circular references be collected
150    println!("\n4. Clear root object status and trigger GC again...");
151    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152    println!(
153        "  Freed {} bytes of memory (circular references correctly collected)",
154        freed
155    );
156
157    Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162    heap: &mut GcHeap,
163    partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165    println!("1. Create complex data structures...");
166
167    // Create multiple nodes
168    let mut root_node =
169        unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170    let mut child1 =
171        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172    let child2 =
173        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174    let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175        .map_err(|(err, _)| err)?;
176
177    // Build tree structure
178    {
179        root_node.with_mut(heap, |n| n.add_child(child1));
180        root_node.with_mut(heap, |n| n.add_child(child2));
181        child1.with_mut(heap, |n| n.add_child(grandchild));
182    }
183
184    // Create data container
185    let container = unsafe {
186        heap.alloc_root_raw(
187            partition,
188            DataContainer {
189                root: root_node,
190                metadata: vec![1, 2, 3],
191                optional_data: Some(child1),
192            },
193        )
194    }
195    .map_err(|(err, _)| err)?;
196
197    println!("  Created tree structure:");
198    println!("    Root -> Child 1 -> Grandchild");
199    println!("    Root -> Child 2");
200    println!("  Created data container");
201
202    // Trigger garbage collection
203    println!("\n2. Trigger garbage collection...");
204    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205    println!("  回收了 {} 字节内存", freed);
206
207    // Verify data structure integrity
208    println!("\n3. Verify data structure integrity...");
209    {
210        println!("  Container root node: {}", container.root.name);
211        println!("  Metadata length: {}", container.metadata.len());
212        println!(
213            "  Optional data exists: {}",
214            container.optional_data.is_some()
215        );
216    }
217
218    Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223    heap: &mut GcHeap,
224    partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226    println!("1. Create object and get reference...");
227
228    let original_ref = unsafe {
229        heap.alloc_raw(
230            partition,
231            TestData {
232                value: 42,
233                name: "test".to_string(),
234            },
235        )
236    }
237    .map_err(|(err, _)| err)?;
238
239    let data_ref = original_ref.deref();
240    println!("  Original reference: {:?}", original_ref);
241    println!("  Data: {:?}", data_ref);
242
243    // Recover GcRef from reference
244    println!("\n2. Recover GcRef from reference...");
245    let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247    match recovered_ref {
248        Some(recovered) => {
249            println!("  Recovery successful: {:?}", recovered);
250            let recovered_data = recovered.deref();
251            println!("  Recovered data: {:?}", recovered_data);
252            println!("  Data equal: {}", data_ref == recovered_data);
253            println!("  Reference equal: {}", original_ref == recovered);
254        }
255        None => println!("  Recovery failed (possibly type registration issue)"),
256    }
257
258    // Test invalid reference recovery - create an object not in GC heap
259    println!("\n3. Test invalid reference recovery...");
260    let local_data = TestData {
261        value: 100,
262        name: "local".to_string(),
263    };
264    let invalid_result = GcRef::try_from_ref(heap, &local_data);
265    println!(
266        "  Invalid reference recovery result: {:?} (should be None)",
267        invalid_result
268    );
269
270    Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275    println!("1. Create two independent heaps...");
276
277    let mut heap1 = new_heap();
278    let mut heap2 = new_heap();
279
280    let partition1 = heap1.create_partition();
281    let partition2 = heap2.create_partition();
282
283    let obj1 = unsafe {
284        heap1.alloc_root_raw(
285            partition1,
286            TestData {
287                value: 1,
288                name: "obj1".to_string(),
289            },
290        )
291    }
292    .map_err(|(e, _)| e)?;
293    let obj2 = unsafe {
294        heap2.alloc_raw(
295            partition2,
296            TestData {
297                value: 2,
298                name: "obj2".to_string(),
299            },
300        )
301    }
302    .map_err(|(e, _)| e)?;
303
304    println!("2. Test object source detection...");
305    assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306    assert!(
307        !heap1.contains(obj2.node_ptr()),
308        "obj2 should not be from heap1"
309    );
310    assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311    assert!(
312        !heap2.contains(obj1.node_ptr()),
313        "obj1 should not be from heap2"
314    );
315
316    println!("  ✓ Cross-context detection correct");
317
318    // Clean up
319    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322    Ok(())
323}
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.
  3. If master and slave belong to different GC partitions, recording a cross-partition reference (xref) so that the slave’s partition can find it during marking.
§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) -> GcPartitionId

Create a new partition.

Examples found in repository?
examples/gc_node_usage.rs (line 53)
51fn main() -> GcResult<()> {
52    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
53    let scope = heap.create_partition();
54
55    let static_ref = alloc_static(&mut heap, scope, 10)?;
56    let other_ref = alloc_other(&mut heap, scope, 20)?;
57
58    println!("Static node value: {}", static_ref._value);
59    println!("Other node value: {}", other_ref._value);
60
61    println!("gc_node_usage example verified");
62
63    Ok(())
64}
More examples
Hide additional examples
examples/advanced_features.rs (line 51)
47fn main() -> GcResult<()> {
48    println!("=== Advanced features example of partitioned garbage collection system ===");
49
50    let mut heap = new_heap();
51    let partition = heap.create_partition();
52
53    // Demonstrate weak reference functionality
54    println!("\n=== Weak reference functionality demonstration ===");
55    demonstrate_weak_references(&mut heap, partition)?;
56
57    // Demonstrate circular reference handling
58    println!("\n=== Circular reference handling demonstration ===");
59    demonstrate_cyclic_references(&mut heap, partition)?;
60
61    // Demonstrate complex data structures
62    println!("\n=== Complex data structures demonstration ===");
63    demonstrate_complex_structures(&mut heap, partition)?;
64
65    // Demonstrate reference recovery functionality
66    println!("\n=== Reference recovery functionality demonstration ===");
67    demonstrate_reference_recovery(&mut heap, partition)?;
68
69    // Demonstrate cross-context detection
70    println!("\n=== Cross-context detection demonstration ===");
71    demonstrate_cross_context_detection()?;
72
73    println!("\nAll advanced feature demonstrations completed!");
74    Ok(())
75}
76
77/// Demonstrate weak reference functionality
78fn demonstrate_weak_references(
79    heap: &mut GcHeap,
80    partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82    println!("1. Create strong and weak references...");
83
84    let strong_ref =
85        unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86            .map_err(|(err, _)| err)?;
87
88    let weak_ref = heap.downgrade(&strong_ref);
89    println!("  Created strong reference: {:?}", strong_ref);
90    println!("  Created weak reference: {:?}", weak_ref);
91
92    // Upgrade weak reference
93    println!("\n2. Upgrade weak reference...");
94    match weak_ref.upgrade(heap) {
95        Some(upgraded) => {
96            let data = upgraded.deref();
97            println!("  Weak reference upgrade successful: '{}'", data);
98            assert_eq!(data, "Strong Reference Data");
99        }
100        None => println!("  Weak reference upgrade failed"),
101    }
102
103    // Try upgrading after releasing strong reference
104    println!("\n3. Upgrade weak reference after releasing strong reference...");
105    heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107    match weak_ref.upgrade(heap) {
108        Some(_) => {
109            println!("  Weak reference can still be upgraded (object may still be in memory)")
110        }
111        None => println!("  Weak reference upgrade failed (object has been collected)"),
112    }
113
114    Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119    heap: &mut GcHeap,
120    partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122    println!("1. Create circular reference nodes...");
123
124    // Create two mutually referencing nodes
125    let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126        .map_err(|(err, _)| err)?;
127    let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128        .map_err(|(err, _)| err)?;
129
130    // Establish circular references
131    {
132        node1.with_mut(heap, |n| n.set_partner(node2));
133        node2.with_mut(heap, |n| n.set_partner(node1));
134    }
135
136    println!("  Created node1: {}", node1.deref());
137    println!("  Created node2: {}", node2.deref());
138
139    // Trigger garbage collection
140    println!("\n2. Trigger garbage collection (circular references still exist)...");
141    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  回收了 {} 字节内存", freed);
143
144    // Verify circular references still exist
145    println!("\n3. Verify circular references...");
146    println!("  Node1's partner: {}", node1.get_partner_name());
147    println!("  Node2's partner: {}", node2.get_partner_name());
148
149    // Clear root object status, let circular references be collected
150    println!("\n4. Clear root object status and trigger GC again...");
151    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152    println!(
153        "  Freed {} bytes of memory (circular references correctly collected)",
154        freed
155    );
156
157    Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162    heap: &mut GcHeap,
163    partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165    println!("1. Create complex data structures...");
166
167    // Create multiple nodes
168    let mut root_node =
169        unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170    let mut child1 =
171        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172    let child2 =
173        unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174    let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175        .map_err(|(err, _)| err)?;
176
177    // Build tree structure
178    {
179        root_node.with_mut(heap, |n| n.add_child(child1));
180        root_node.with_mut(heap, |n| n.add_child(child2));
181        child1.with_mut(heap, |n| n.add_child(grandchild));
182    }
183
184    // Create data container
185    let container = unsafe {
186        heap.alloc_root_raw(
187            partition,
188            DataContainer {
189                root: root_node,
190                metadata: vec![1, 2, 3],
191                optional_data: Some(child1),
192            },
193        )
194    }
195    .map_err(|(err, _)| err)?;
196
197    println!("  Created tree structure:");
198    println!("    Root -> Child 1 -> Grandchild");
199    println!("    Root -> Child 2");
200    println!("  Created data container");
201
202    // Trigger garbage collection
203    println!("\n2. Trigger garbage collection...");
204    let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205    println!("  回收了 {} 字节内存", freed);
206
207    // Verify data structure integrity
208    println!("\n3. Verify data structure integrity...");
209    {
210        println!("  Container root node: {}", container.root.name);
211        println!("  Metadata length: {}", container.metadata.len());
212        println!(
213            "  Optional data exists: {}",
214            container.optional_data.is_some()
215        );
216    }
217
218    Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223    heap: &mut GcHeap,
224    partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226    println!("1. Create object and get reference...");
227
228    let original_ref = unsafe {
229        heap.alloc_raw(
230            partition,
231            TestData {
232                value: 42,
233                name: "test".to_string(),
234            },
235        )
236    }
237    .map_err(|(err, _)| err)?;
238
239    let data_ref = original_ref.deref();
240    println!("  Original reference: {:?}", original_ref);
241    println!("  Data: {:?}", data_ref);
242
243    // Recover GcRef from reference
244    println!("\n2. Recover GcRef from reference...");
245    let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247    match recovered_ref {
248        Some(recovered) => {
249            println!("  Recovery successful: {:?}", recovered);
250            let recovered_data = recovered.deref();
251            println!("  Recovered data: {:?}", recovered_data);
252            println!("  Data equal: {}", data_ref == recovered_data);
253            println!("  Reference equal: {}", original_ref == recovered);
254        }
255        None => println!("  Recovery failed (possibly type registration issue)"),
256    }
257
258    // Test invalid reference recovery - create an object not in GC heap
259    println!("\n3. Test invalid reference recovery...");
260    let local_data = TestData {
261        value: 100,
262        name: "local".to_string(),
263    };
264    let invalid_result = GcRef::try_from_ref(heap, &local_data);
265    println!(
266        "  Invalid reference recovery result: {:?} (should be None)",
267        invalid_result
268    );
269
270    Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275    println!("1. Create two independent heaps...");
276
277    let mut heap1 = new_heap();
278    let mut heap2 = new_heap();
279
280    let partition1 = heap1.create_partition();
281    let partition2 = heap2.create_partition();
282
283    let obj1 = unsafe {
284        heap1.alloc_root_raw(
285            partition1,
286            TestData {
287                value: 1,
288                name: "obj1".to_string(),
289            },
290        )
291    }
292    .map_err(|(e, _)| e)?;
293    let obj2 = unsafe {
294        heap2.alloc_raw(
295            partition2,
296            TestData {
297                value: 2,
298                name: "obj2".to_string(),
299            },
300        )
301    }
302    .map_err(|(e, _)| e)?;
303
304    println!("2. Test object source detection...");
305    assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306    assert!(
307        !heap1.contains(obj2.node_ptr()),
308        "obj2 should not be from heap1"
309    );
310    assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311    assert!(
312        !heap2.contains(obj1.node_ptr()),
313        "obj1 should not be from heap2"
314    );
315
316    println!("  ✓ Cross-context detection correct");
317
318    // Clean up
319    heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320    heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322    Ok(())
323}
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();
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();
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                        nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123                    }
124                }
125                // Every 10 nodes form a cycle
126                if i % 10 == 0 && i + 9 < size {
127                    let n = nodes[i];
128                    nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129                }
130            }
131        }
132        let graph_duration = graph_start.elapsed();
133
134        println!("  Built complex object graph in: {:?}", graph_duration);
135
136        // Measure GC performance
137        let gc_start = Instant::now();
138        let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139        let gc_duration = gc_start.elapsed();
140
141        println!("  GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142        println!(
143            "  Object graph complexity: average {} neighbors per node",
144            if size > 0 { (size * 5) / size } else { 0 }
145        );
146    }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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();
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();
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 60)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
Source

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

Remove a partition, and dispose unused nodes. For non-root partition, migrate xref nodes is optionally performed.

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

pub fn partition(&self, partition_id: GcPartitionId) -> Option<&GcPartition>

Get partition information

Examples found in repository?
examples/performance_benchmark.rs (line 166)
150fn benchmark_memory_efficiency() {
151    println!("\nTesting memory usage efficiency...");
152
153    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154    context.set_memory_limit(1024 * 1024); // 1MB global limit
155    let partition = context.create_partition();
156
157    // Allocate many small objects
158    let small_objects_count = 1000;
159    let mut small_objects = Vec::new();
160
161    for _i in 0..small_objects_count {
162        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163        small_objects.push(obj);
164    }
165
166    if let Some(partition_info) = context.partition(partition) {
167        let used = partition_info.memory_used();
168        let limit = context.memory_limit();
169        let efficiency = if limit > 0 {
170            (used as f64 / limit as f64) * 100.0
171        } else {
172            0.0
173        };
174
175        println!("  After allocating {} small objects:", small_objects_count);
176        println!(
177            "  Memory usage: {}/{} bytes ({:.1}%)",
178            used, limit, efficiency
179        );
180        println!(
181            "  Average overhead per object: {} bytes",
182            if small_objects_count > 0 {
183                used / small_objects_count
184            } else {
185                0
186            }
187        );
188    }
189
190    // Collect all objects
191    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192    println!("  Collected all objects, freed {} bytes", freed);
193
194    // Verify complete memory collection
195    if let Some(partition_info) = context.partition(partition) {
196        let used_after = partition_info.memory_used();
197        println!("  Memory usage after collection: {} bytes", used_after);
198        println!(
199            "  Memory collection rate: {:.1}%",
200            if freed > 0 {
201                (freed as f64 / (freed + used_after) as f64) * 100.0
202            } else {
203                0.0
204            }
205        );
206    }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211    println!("\nTesting automatic GC threshold performance...");
212
213    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214    context.set_memory_limit(2048); // 2KB global limit
215    let partition = context.create_partition();
216
217    // Set automatic GC threshold to 1.5KB
218    context.set_gc_threshold(1500);
219
220    // Allocate objects until automatic GC is triggered
221    let mut allocated_bytes = 0;
222    let mut object_count = 0;
223
224    println!("  Allocating objects until automatic GC is triggered...");
225
226    for _i in 0..100 {
227        // Try at most 100 times
228        // Allocate objects of about 100 bytes
229        let node = SimpleNode {
230            _data: vec![0u8; 100],
231        };
232        match unsafe { context.alloc_raw(partition, node) } {
233            Ok(_gc_ref) => {
234                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235                object_count += 1;
236
237                // Check if approaching threshold
238                if let Some(partition_info) = context.partition(partition)
239                    && partition_info.memory_used() >= 1500
240                {
241                    println!(
242                        "  Reached automatic GC threshold, allocated {} objects",
243                        object_count
244                    );
245                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
246                    println!(
247                        "  Actual memory usage: {} bytes",
248                        partition_info.memory_used()
249                    );
250                    break;
251                }
252            }
253            Err(_) => {
254                println!("  Allocation failed, automatic GC may have been triggered");
255                break;
256            }
257        }
258    }
259
260    // Manually trigger GC to see effect
261    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262    println!("  Manual GC freed {} bytes", freed);
263}
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();
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 90)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
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 56)
49fn main() -> GcResult<()> {
50    println!("=== Basic usage example of partitioned garbage collection system ===");
51
52    // Create garbage collection context
53    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55    println!("Initial state:");
56    println!("  Number of partitions: {}", heap.partition_ids().len());
57
58    // Create two partitions
59    println!("\nCreate partitions:");
60    let partition1 = heap.create_partition();
61    let partition2 = heap.create_partition();
62    println!("  Created partition1: {:?}", partition1);
63    println!("  Created partition2: {:?}", partition2);
64    println!("  Number of partitions: {}", heap.partition_ids().len());
65
66    // Allocate objects in partition1
67    println!("\nAllocate objects in partition1:");
68    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69        .map_err(|(err, _)| err)?;
70    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72        .map_err(|(err, _)| err)?;
73
74    println!("  Created string: '{}'", obj1.deref());
75    println!("  Created number: {}", obj2.deref());
76    println!("  Created string: '{}'", obj3.deref());
77
78    // Allocate objects in partition2
79    println!("\nAllocate objects in partition2:");
80    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81        .map_err(|(err, _)| err)?;
82    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84    println!("  Created string: '{}'", obj4.deref());
85    println!("  Created number: {}", obj5.deref());
86
87    // Display partition status
88    println!("\nPartition status:");
89    for partition_id in heap.partition_ids() {
90        if let Some(partition) = heap.partition(partition_id) {
91            let limit = heap.memory_limit();
92            let usage = if limit > 0 {
93                format!(
94                    "{}/{} bytes ({:.1}%)",
95                    partition.memory_used(),
96                    limit,
97                    (partition.memory_used() as f64 / limit as f64) * 100.0
98                )
99            } else {
100                format!("{}/∞ bytes", partition.memory_used())
101            };
102            println!(
103                "  {:?}: {} [自动GC: {}]",
104                partition_id,
105                usage,
106                if heap.gc_threshold() > 0 {
107                    "Enabled"
108                } else {
109                    "Disabled"
110                }
111            );
112        }
113    }
114
115    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116    // No explicit `set_root` calls are needed for them.
117    println!("\nRoot objects are held by variables:");
118    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
119
120    // Manually trigger garbage collection for partition1
121    println!("\nManually trigger garbage collection for partition1...");
122    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123    println!("  Collected {} bytes", freed);
124
125    // Verify root objects are still valid
126    println!("\nVerify partition1 root objects are still valid:");
127    println!("  Object1: '{}'", obj1.deref());
128    println!("  Object2: {}", obj2.deref());
129
130    // Manually trigger garbage collection for partition2
131    println!("\nManually trigger garbage collection for partition2...");
132    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133    println!("  Collected {} bytes", freed);
134
135    // Verify partition2 root objects are still valid
136    println!("\nVerify partition2 root objects are still valid:");
137    println!("  Object4: '{}'", obj4.deref());
138
139    // Trigger garbage collection for partition1 again to collect unreferenced objects
140    println!("\nTrigger garbage collection for partition1 again...");
141    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142    // to test collection. For this example, we'll just collect other garbage.
143    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144    println!("  Collected {} bytes", freed);
145
146    // Verify remaining root objects are still valid
147    println!("\nVerify remaining root objects are still valid:");
148    println!("  Object1: '{}'", obj1.deref());
149    println!("  Object2: {} (still a root)", obj2.deref());
150
151    // Demonstrate automatic garbage collection
152    println!("\nDemonstrate automatic garbage collection...");
153
154    // Create a small partition to demonstrate automatic GC
155    let small_partition = heap.create_partition();
156
157    // Allocate multiple objects to fill partition
158    for i in 0..5 {
159        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160            .map_err(|(err, _)| err)?;
161    }
162
163    println!("  Allocated 5 objects in small partition");
164
165    // Demonstrate weak references
166    println!("\nDemonstrate weak references:");
167    let weak_ref = heap.downgrade(&obj1);
168    println!("  Created weak reference: {:?}", weak_ref);
169
170    // Upgrade weak reference
171    match weak_ref.upgrade(&heap) {
172        Some(strong_ref) => {
173            println!(
174                "  Weak reference upgrade successful: '{}'",
175                strong_ref.deref()
176            );
177        }
178        None => {
179            println!("  Weak reference upgrade failed");
180        }
181    }
182
183    // Demonstrate complex types with GC references
184    println!("\nDemonstrate complex types with GC references:");
185    let mut node1 =
186        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187    let mut node2 =
188        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190    // Establish references between nodes
191    {
192        node1.with_mut(&mut heap, |n| n.add_child(node2));
193        node2.with_mut(&mut heap, |n| n.add_child(node1));
194    }
195
196    println!("  Created node1: {}", node1.deref());
197    println!("  Created node2: {}", node2.deref());
198
199    // Trigger garbage collection, verify circular references are handled correctly
200    println!("\nGarbage collection for handling circular references...");
201    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202    println!("  回收了 {} 字节内存", freed);
203
204    // Demonstrate partition deletion
205    println!("\nDemonstrate partition deletion:");
206
207    // Create an empty partition
208    let empty_partition = heap.create_partition();
209    println!("  Created empty partition: {:?}", empty_partition);
210
211    // Delete empty partition
212    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213    println!("  Deleted empty partition successfully");
214
215    // Delete non-empty partition
216    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217    println!("  Deleted non-empty partition successfully");
218
219    println!("\nExample completed!");
220    Ok(())
221}
Source§

impl GcHeap

Source

pub fn scope_max_depth(&self) -> u8

Source

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

get scope by depth (peek, without modifying stack)

Source

pub fn current_scope(&self) -> Option<&GcScopeState<'_>>

Source

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

Source

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

Source

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

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

pub fn upgrade<T: GcNode>(&self, weak_ref: &GcWeak<T>) -> Option<GcRef<T>>

Upgrade weak reference

Source§

impl GcHeap

Source

pub const fn set_xref( &mut self, from_scope: GcPartitionId, node: NonNull<GcHead>, ) -> bool

👎Deprecated

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 Freeze for GcHeap

§

impl !RefUnwindSafe for GcHeap

§

impl !Send for GcHeap

§

impl !Sync for GcHeap

§

impl Unpin for GcHeap

§

impl UnsafeUnpin for GcHeap

§

impl !UnwindSafe 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.