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?
84fn get_running_project(xml: &str, system: Rc<StdSystem<C>>) -> EnvArena {
85 EnvArena::new(|mc| {
86 let parser = ast::Parser::default();
87 let ast = parser.parse(xml).unwrap();
88 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
89
90 let (bytecode, init_info, locs, _) = ByteCode::compile(&ast.roles[0]).unwrap();
91
92 let mut proj = Project::from_init(mc, &init_info, Rc::new(bytecode), Settings::default(), system);
93 proj.input(mc, Input::Start); // this is equivalent to clicking the green flag button
94
95 Env { proj: Gc::new(mc, RefLock::new(proj)), locs }
96 })
97}
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?
99fn main() {
100 // read in an xml file whose path is given as a command line argument
101 let args = std::env::args().collect::<Vec<_>>();
102 if args.len() != 2 {
103 panic!("usage: {} [xml file]", &args[0]);
104 }
105 let mut xml = String::new();
106 std::fs::File::open(&args[1]).expect("failed to open file").read_to_string(&mut xml).expect("failed to read file");
107
108 // create a new shared clock and start a thread that updates it at our desired interval
109 let clock = Arc::new(Clock::new(UtcOffset::UTC, Some(Precision::Medium)));
110 let clock_clone = clock.clone();
111 std::thread::spawn(move || loop {
112 std::thread::sleep(CLOCK_INTERVAL);
113 clock_clone.update();
114 });
115
116 // create a custom config for the system - in this simple example we just implement the say/think blocks to print to stdout
117 let config = Config::<C, StdSystem<C>> {
118 request: None,
119 command: Some(Rc::new(|_mc, key, command, _proc| match command {
120 Command::Print { style: _, value } => {
121 if let Some(value) = value {
122 println!("{value:?}");
123 }
124 key.complete(Ok(())); // any request that you handle must be completed - otherwise the calling process will hang forever
125 CommandStatus::Handled
126 }
127 _ => CommandStatus::UseDefault { key, command }, // anything you don't handle should return the key and command to invoke the default behavior instead
128 })),
129 };
130
131 // initialize our system with all the info we've put together
132 let system = Rc::new(StdSystem::new_sync(CompactString::new(BASE_URL), None, config, clock.clone()));
133 let mut env = get_running_project(&xml, system);
134
135 // begin running the code - these are some helpers to make things more efficient in terms of memory and cpu resources
136 let mut idle_sleeper = IdleAction::new(YIELDS_BEFORE_SLEEP, Box::new(|| std::thread::sleep(IDLE_SLEEP_TIME)));
137 let mut next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
138 loop {
139 env.mutate(|mc, env| {
140 let mut proj = env.proj.borrow_mut(mc);
141 for _ in 0..1024 {
142 // step the virtual machine forward by one bytecode instruction
143 let res = proj.step(mc);
144 if let ProjectStep::Error { error, proc } = &res {
145 // if we get an error, we can generate an error summary including a stack trace - here we just print out the result
146 let trace = ErrorSummary::extract(error, proc, &env.locs);
147 println!("error: {error:?}\ntrace: {trace:?}");
148 }
149 // this takes care of performing thread sleep if we get a bunch of no-ops from proj.step back to back
150 idle_sleeper.consume(&res);
151 }
152 });
153 // if it's time for us to do garbage collection, do it and reset the next collection time
154 if clock.read(Precision::Low) >= next_collect {
155 env.collect_all();
156 next_collect = clock.read(Precision::Medium) + COLLECT_INTERVAL;
157 }
158 }
159}
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> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string()
Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString
. Read moreSource§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string
, but without panic on OOM.