Skip to main content

GcRef

Struct GcRef 

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

Garbage collection reference

Implementations§

Source§

impl<T: GcNode> GcRef<T>

Source

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

Create GcRef from &T reference

This method verifies that the passed reference comes from a valid GC object. It ensures safety by checking if the corresponding GcHead is in the GC context.

§Parameters
  • data_ref: Reference to convert, must come from valid GcRef object
§Return Value
  • Some(GcRef<T>): If reference comes from valid GC object
  • None: If reference is not from GC object or object is invalid
§Safety

Caller must ensure the passed reference indeed comes from a valid GcRef object.

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

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

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

§Safety

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

Source

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

Examples found in repository?
examples/advanced_features.rs (line 132)
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}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 122)
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}
examples/basic_usage.rs (line 192)
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 as_ptr(&self) -> NonNull<T>

Source

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

Source

pub fn is_root(&self) -> bool

check if this is root object

Source

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

get node raw pointer

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 node_info(&self) -> &GcHead

get node info

Trait Implementations§

Source§

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

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

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

Source§

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

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

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

Source§

type Target = T

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

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

Source§

fn deref_mut(&mut self) -> &mut Self::Target

FIXME: DerefMut breaks gc node write barrier. This should be disabled.

Source§

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

Source§

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

Converts to this type from the input type.
Source§

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

Source§

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

Converts to this type from the input type.
Source§

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

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

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

Source§

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

Auto Trait Implementations§

§

impl<T> Freeze for GcRef<T>

§

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

§

impl<T> !Send for GcRef<T>

§

impl<T> !Sync for GcRef<T>

§

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

§

impl<T> UnsafeUnpin for GcRef<T>

§

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

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

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

Source§

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

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

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

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

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

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

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

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

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

Source§

type Error = Infallible

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

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

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.