pub struct Gc<'gc, T>where
T: 'gc + ?Sized,{ /* private fields */ }
Expand description
A garbage collected pointer to a type T. Implements Copy, and is implemented as a plain machine
pointer. You can only allocate Gc
pointers through a &Mutation<'gc>
inside an arena type,
and through “generativity” such Gc
pointers may not escape the arena they were born in or
be stored inside TLS. This, combined with correct Collect
implementations, means that Gc
pointers will never be dangling and are always safe to access.
Implementations§
Source§impl<'gc, T> Gc<'gc, T>where
T: Collect + 'gc,
impl<'gc, T> Gc<'gc, T>where
T: Collect + 'gc,
Sourcepub fn new(mc: &Mutation<'gc>, t: T) -> Gc<'gc, T>
pub fn new(mc: &Mutation<'gc>, t: T) -> Gc<'gc, T>
Examples found in repository?
84 85 86 87 88 89 90 91 92 93 94 95 96 97
fn get_running_project(xml: &str, system: Rc<StdSystem<C>>) -> EnvArena {
EnvArena::new(|mc| {
let parser = ast::Parser::default();
let ast = parser.parse(xml).unwrap();
assert_eq!(ast.roles.len(), 1); // this should be handled more elegantly in practice - for the sake of this example, we only allow one role
let (bytecode, init_info, locs, _) = ByteCode::compile(&ast.roles[0]).unwrap();
let mut proj = Project::from_init(mc, &init_info, Rc::new(bytecode), Settings::default(), system);
proj.input(mc, Input::Start); // this is equivalent to clicking the green flag button
Env { proj: Gc::new(mc, RefLock::new(proj)), locs }
})
}
Source§impl<'gc, T> Gc<'gc, T>where
T: 'gc,
impl<'gc, T> Gc<'gc, T>where
T: 'gc,
Source§impl<'gc, T> Gc<'gc, T>where
T: 'gc + ?Sized,
impl<'gc, T> Gc<'gc, T>where
T: 'gc + ?Sized,
Sourcepub fn as_ref(self) -> &'gc T
pub fn as_ref(self) -> &'gc T
Obtains a long-lived reference to the contents of this Gc
.
Unlike AsRef
or Deref
, the returned reference isn’t bound to the Gc
itself, and
will stay valid for the entirety of the current arena callback.
pub fn downgrade(this: Gc<'gc, T>) -> GcWeak<'gc, T>
Sourcepub fn write(mc: &Mutation<'gc>, gc: Gc<'gc, T>) -> &'gc Write<T>
pub fn write(mc: &Mutation<'gc>, gc: Gc<'gc, T>) -> &'gc Write<T>
Triggers a write barrier on this Gc
, allowing for further safe mutation.
Sourcepub fn ptr_eq(this: Gc<'gc, T>, other: Gc<'gc, T>) -> bool
pub fn ptr_eq(this: Gc<'gc, T>, other: Gc<'gc, T>) -> bool
Returns true if two Gc
s point to the same allocation.
Similarly to Rc::ptr_eq
and Arc::ptr_eq
, this function ignores the metadata of dyn
pointers.
pub fn as_ptr(gc: Gc<'gc, T>) -> *const T
Sourcepub fn is_dead(_: &Finalization<'gc>, gc: Gc<'gc, T>) -> bool
pub fn is_dead(_: &Finalization<'gc>, gc: Gc<'gc, T>) -> bool
Returns true when a pointer is dead during finalization. This is equivalent to
GcWeak::is_dead
for strong pointers.
Any strong pointer reachable from the root will never be dead, BUT there can be strong pointers reachable only through other weak pointers that can be dead.
Sourcepub fn resurrect(fc: &Finalization<'gc>, gc: Gc<'gc, T>)
pub fn resurrect(fc: &Finalization<'gc>, gc: Gc<'gc, T>)
Manually marks a dead Gc
pointer as reachable and keeps it alive.
Equivalent to GcWeak::resurrect
for strong pointers. Manually marks this pointer and
all transitively held pointers as reachable, thus keeping them from being dropped this
collection cycle.
Source§impl<'gc, T> Gc<'gc, RefLock<T>>where
T: 'gc + ?Sized,
impl<'gc, T> Gc<'gc, RefLock<T>>where
T: 'gc + ?Sized,
pub fn borrow(self) -> Ref<'gc, T>
pub fn try_borrow(self) -> Result<Ref<'gc, T>, BorrowError>
Sourcepub fn borrow_mut(self, mc: &Mutation<'gc>) -> RefMut<'gc, T>
pub fn borrow_mut(self, mc: &Mutation<'gc>) -> RefMut<'gc, T>
Examples found in repository?
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
fn main() {
// read in an xml file whose path is given as a command line argument
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 2 {
panic!("usage: {} [xml file]", &args[0]);
}
let mut xml = String::new();
std::fs::File::open(&args[1]).expect("failed to open file").read_to_string(&mut xml).expect("failed to read file");
// create a new shared clock and start a thread that updates it at our desired interval
let clock = Arc::new(Clock::new(UtcOffset::UTC, Some(Precision::Medium)));
let clock_clone = clock.clone();
std::thread::spawn(move || loop {
std::thread::sleep(CLOCK_INTERVAL);
clock_clone.update();
});
// create a custom config for the system - in this simple example we just implement the say/think blocks to print to stdout
let config = Config::<C, StdSystem<C>> {
request: None,
command: Some(Rc::new(|_mc, key, command, _proc| match command {
Command::Print { style: _, value } => {
if let Some(value) = value {
println!("{value:?}");
}
key.complete(Ok(())); // any request that you handle must be completed - otherwise the calling process will hang forever
CommandStatus::Handled
}
_ => CommandStatus::UseDefault { key, command }, // anything you don't handle should return the key and command to invoke the default behavior instead
})),
};
// initialize our system with all the info we've put together
let system = Rc::new(StdSystem::new_sync(CompactString::new(BASE_URL), None, config, clock.clone()));
let mut env = get_running_project(&xml, system);
// begin running the code - these are some helpers to make things more efficient in terms of memory and cpu resources
let mut idle_sleeper = IdleAction::new(YIELDS_BEFORE_SLEEP, Box::new(|| std::thread::sleep(IDLE_SLEEP_TIME)));
let mut next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
loop {
env.mutate(|mc, env| {
let mut proj = env.proj.borrow_mut(mc);
for _ in 0..1024 {
// step the virtual machine forward by one bytecode instruction
let res = proj.step(mc);
if let ProjectStep::Error { error, proc } = &res {
// if we get an error, we can generate an error summary including a stack trace - here we just print out the result
let trace = ErrorSummary::extract(error, proc, &env.locs);
println!("error: {error:?}\ntrace: {trace:?}");
}
// this takes care of performing thread sleep if we get a bunch of no-ops from proj.step back to back
idle_sleeper.consume(&res);
}
});
// if it's time for us to do garbage collection, do it and reset the next collection time
if clock.read(Precision::Low) >= next_collect {
env.collect_all();
next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
}
}
}
pub fn try_borrow_mut( self, mc: &Mutation<'gc>, ) -> Result<RefMut<'gc, T>, BorrowMutError>
Trait Implementations§
Source§impl<'gc, T> Collect for Gc<'gc, T>where
T: 'gc + ?Sized,
impl<'gc, T> Collect for Gc<'gc, T>where
T: 'gc + ?Sized,
Source§fn trace(&self, cc: &Collection)
fn trace(&self, cc: &Collection)
Collect::trace
on all held Gc
pointers. If this type holds inner types that
implement Collect
, a valid implementation would simply call Collect::trace
on all the
held values to ensure this.Source§fn needs_trace() -> boolwhere
Self: Sized,
fn needs_trace() -> boolwhere
Self: Sized,
Gc
pointer and trace
is unnecessary
to call, you may implement this method and return false. The default implementation returns
true, signaling that Collect::trace
must be called.Source§impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<Closure<'gc, C, S>>>> for Value<'gc, C, S>
impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<Closure<'gc, C, S>>>> for Value<'gc, C, S>
Source§impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<Entity<'gc, C, S>>>> for Value<'gc, C, S>
impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<Entity<'gc, C, S>>>> for Value<'gc, C, S>
Source§impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<VecDeque<Value<'gc, C, S>>>>> for Value<'gc, C, S>
impl<'gc, C: CustomTypes<S>, S: System<C>> From<Gc<'gc, RefLock<VecDeque<Value<'gc, C, S>>>>> for Value<'gc, C, S>
Source§impl<'gc, T> Ord for Gc<'gc, T>
impl<'gc, T> Ord for Gc<'gc, T>
1.21.0 · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl<'gc, T> PartialOrd for Gc<'gc, T>where
T: PartialOrd + 'gc + ?Sized,
impl<'gc, T> PartialOrd for Gc<'gc, T>where
T: PartialOrd + 'gc + ?Sized,
impl<'gc, T> Copy for Gc<'gc, T>where
T: 'gc + ?Sized,
impl<'gc, T> Eq for Gc<'gc, T>
Auto Trait Implementations§
impl<'gc, T> Freeze for Gc<'gc, T>where
T: ?Sized,
impl<'gc, T> !RefUnwindSafe for Gc<'gc, T>
impl<'gc, T> !Send for Gc<'gc, T>
impl<'gc, T> !Sync for Gc<'gc, T>
impl<'gc, T> Unpin for Gc<'gc, T>where
T: ?Sized,
impl<'gc, T> !UnwindSafe for Gc<'gc, T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString
. Read more