#[cfg(feature = "experimental-threads")] #[cfg_attr(published_docs, doc(cfg(feature = "experimental-threads")))]
use godot_cell::blocking::{GdCell, InaccessibleGuard, MutGuard, RefGuard};
#[cfg(not(feature = "experimental-threads"))] #[cfg_attr(published_docs, doc(cfg(not(feature = "experimental-threads"))))]
use godot_cell::panicking::{GdCell, InaccessibleGuard, MutGuard, RefGuard};
use crate::obj::{Base, GodotClass};
use crate::storage::{AtomicLifecycle, DebugBorrowTracker, Lifecycle, Storage, StorageRefCounted};
pub struct InstanceStorage<T: GodotClass> {
user_instance: GdCell<T>,
pub(super) base: Base<T::Base>,
pub(super) lifecycle: AtomicLifecycle,
borrow_tracker: DebugBorrowTracker,
}
unsafe impl<T: GodotClass> Storage for InstanceStorage<T> {
type Instance = T;
fn construct(
user_instance: Self::Instance,
base: Base<<Self::Instance as GodotClass>::Base>,
) -> Self {
super::log_construct::<T>(&base);
Self {
user_instance: GdCell::new(user_instance),
base,
lifecycle: AtomicLifecycle::new(Lifecycle::Alive),
borrow_tracker: DebugBorrowTracker::new(),
}
}
fn is_bound(&self) -> bool {
self.user_instance.is_currently_bound()
}
fn base(&self) -> &Base<<Self::Instance as GodotClass>::Base> {
&self.base
}
fn get(&self) -> RefGuard<'_, T> {
let guard = self
.user_instance
.borrow()
.unwrap_or_else(|e| super::bind_failed::<T>(e, &self.borrow_tracker));
self.borrow_tracker.track_ref_borrow();
guard
}
fn get_mut(&self) -> MutGuard<'_, T> {
let guard = self
.user_instance
.borrow_mut()
.unwrap_or_else(|e| super::bind_mut_failed::<T>(e, &self.borrow_tracker));
self.borrow_tracker.track_mut_borrow();
guard
}
fn get_inaccessible<'a: 'b, 'b>(
&'a self,
value: &'b mut Self::Instance,
) -> InaccessibleGuard<'b, T> {
self.user_instance
.make_inaccessible(value)
.unwrap_or_else(|e| super::bug_inaccessible::<T>(e))
}
fn get_lifecycle(&self) -> Lifecycle {
self.lifecycle.get()
}
fn set_lifecycle(&self, lifecycle: Lifecycle) {
self.lifecycle.set(lifecycle)
}
}
impl<T: GodotClass> StorageRefCounted for InstanceStorage<T> {
fn on_inc_ref(&self) {
super::log_inc_ref(self);
}
fn on_dec_ref(&self) {
super::log_dec_ref(self);
}
}
impl<T: GodotClass> Drop for InstanceStorage<T> {
fn drop(&mut self) {
super::log_drop(self);
}
}