pub unsafe trait GcContext: Sized {
    type System: GcSystem<Context = Self, Id = Self::Id>;
    type Id: CollectorId;
    unsafe fn unchecked_safepoint<T: Trace>(&self, root: &mut &mut T);
unsafe fn freeze(&mut self);
unsafe fn unfreeze(&mut self);
unsafe fn recurse_context<T, F, R>(&self, root: &mut &mut T, func: F) -> R
    where
        T: Trace,
        F: for<'gc> FnOnce(&'gc mut Self, &'gc mut T) -> R
;
fn system(&self) -> &Self::System;
fn id(&self) -> Self::Id; unsafe fn basic_safepoint<T: Trace>(&mut self, root: &mut &mut T) { ... }
unsafe fn rebrand_static<T>(&self, value: T) -> T::Branded
    where
        T: GcRebrand<'static, Self::Id>,
        T::Branded: Sized
, { ... }
unsafe fn rebrand_self<'gc, T>(&'gc self, value: T) -> T::Branded
    where
        T: GcRebrand<'gc, Self::Id>,
        T::Branded: Sized
, { ... } }
Expand description

The context of garbage collection, which can be frozen at a safepoint.

This is essentially used to maintain a shadow-stack to a set of roots, which are guarenteed not to be collected until a safepoint.

This context doesn’t necessarily support allocation (see GcSimpleAlloc for that).

Associated Types

The system used with this context

The type of ids used in the system

Required methods

Potentially perform a garbage collection, freeing all objects that aren’t reachable from the specified root.

This is a less safe version of GcContext::basic_safepoint that doesn’t explicitly mark this context as “mutated”. However, just like any other safepoint, it still logically invalidates all unreachable objects because the collector might free them.

Safety

All objects that are potentially in-use must be reachable from the specified root. Otherwise, they may be accidentally freed during garbage collection.

It is the user’s responsibility to check this, since this doesn’t statically invalidate (or mutate) the outstanding references.

Inform the garbage collection system we are at a safepoint and are ready for a potential garbage collection.

Unlike a basic_safepoint, the collector continues to stay at the safepoint instead of returning immediately. The context can’t be used for anything (including allocations), until it is unfrozen.

This allows other threads to perform collections while this thread does other work (without using the GC).

The current contexts roots are considered invalid for the duration of the collection, since the collector could potentially relocate them.

Any parent contexts are fine and their roots will be preserved by collections.

Safety

Assumes this context is valid and not already frozen.

Don’t invoke this directly

Unfreeze this context, allowing it to be used again.

Safety

Must be a valid context! Must be currently frozen!

Don’t invoke this directly

Invoke the closure with a temporary GcContext, preserving the specified object as a root of garbage collection.

This will add the specified root to the shadow stack before invoking the closure. Therefore, any safepoints invoked inside the closure/sub-function will implicitly preserve all objects reachable from the root in the parent function.

This doesn’t nessicarrily imply a safepoint, although its wrapper macro (safepoint_recurse!) typically does.

Safety

All objects that are in use must be reachable from the specified root.

The specified closure could trigger a collection in the sub-context, so all live objects in the parent function need to be reachable from the specified root.

See the safepoint_recurse! macro for a safe wrapper

Get the GcSystem associated with this context

Get the id of this context

Provided methods

Potentially perform a garbage collection, freeing all objects that aren’t reachable from the specified root.

This is what the safepoint! macro expands to internally. For example

fn example<'gc>(ctx: &'gc mut ExampleContext, root: Gc<'gc, Obj>) {
    let temp = ctx.alloc(Obj { val: 12 }); // Lives until the call to 'basic_safepoint'
    assert_eq!(temp.val, 12); // VALID
    // This is what `let root = safepoint!(ctx, root)` would expand to:
    let root = unsafe {
        /*
         * Change the lifetime of root from 'gc -> 'static
         * This is necessary so the mutation of 'basic_safepoint'
         * wont invalidate it.
         */
        let mut preserved_root: Gc<'static, Obj> = ctx.rebrand_static(root);
        /*
         * This invalidates 'temp' (because it mutates the owning context)
         * However, preserved_root is fine because it has been changed the 'static
         * lifetime.
         */
        ctx.basic_safepoint(&mut &mut preserved_root);
        /*
         *  It would be unsafe for the user to access
         * preserved_root, because its lifetime of 'static is too large.
         * The call to 'rebrand_self' changes the lifetime of preserved_root
         * back to the (new) lifetime of the context.
         *
         * The safe result is returned as the result of the block.
         * The user has chosen to re-assign the result to the `root` variable
         * via `let root = safepoint!(ctx, root)`.
         */
        ctx.rebrand_self(preserved_root)
    };
    // assert_eq!(temp.val, 12); // INVALID. `temp` was mutated and bound to the old lifetime
    assert_eq!(root.val, 4); // VALID - The lifetime has been updated
}
Safety

Any garbage collected objects not reachable from the roots are invalidated after this method.

The user must ensure that invalidated objects are not used after the safepoint, although the (logical) mutation of the context should significantly assist with that.

Rebrand to the specified root so that it lives for the 'static lifetime.

Safety

This function is unsafe to use directly.

It should only be used as part of the safepoint! macro.

Rebrand the specified root so that it lives for the lifetime of this context.

This effectively undoes the effect of GcContext::rebrand_static.

Safety

This function is unsafe to use directly.

It should only be used as part of the safepoint! macro.

Implementors