Struct netsblox_vm::gc::Gc
source · 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?
examples/basic.rs (line 90)
79 80 81 82 83 84 85 86 87 88 89 90 91 92
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.
pub fn ptr_eq(this: Gc<'gc, T>, other: Gc<'gc, T>) -> bool
pub fn as_ptr(gc: Gc<'gc, T>) -> *const T
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?
examples/basic.rs (line 135)
94 95 96 97 98 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
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)
Must call
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,
As an optimization, if this type can never hold a
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,
Compares and returns the maximum of two values. Read more
source§impl<'gc, T> PartialEq for Gc<'gc, T>
impl<'gc, T> PartialEq for Gc<'gc, T>
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,
source§fn le(&self, other: &Gc<'gc, T>) -> bool
fn le(&self, other: &Gc<'gc, T>) -> bool
This method tests less than or equal to (for
self
and other
) and is used by the <=
operator. Read moreimpl<'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> !RefUnwindSafe for Gc<'gc, T>
impl<'gc, T> !Send for Gc<'gc, T>
impl<'gc, T> !Sync for Gc<'gc, T>
impl<'gc, T: ?Sized> Unpin for Gc<'gc, T>
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
Mutably borrows from an owned value. Read more
§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key
and return true
if they are equal.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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
Converts the given value to a
CompactString
. Read more