cranpose_core/
runtime_cell.rs1use std::{fmt, hash::Hash, marker::PhantomData, rc::Rc};
4
5use crate::runtime::{self, RuntimeHandle, RuntimeId, StateId};
6
7pub struct RuntimeCell<T: 'static> {
31 id: StateId,
32 runtime_id: RuntimeId,
33 _marker: PhantomData<fn() -> T>,
34}
35
36impl<T: 'static> RuntimeCell<T> {
37 pub fn new(value: T) -> Self {
39 Self::with_runtime(value, crate::hooks::current_runtime("RuntimeCell::new"))
40 }
41
42 pub fn with_runtime(value: T, runtime: RuntimeHandle) -> Self {
44 Self {
45 id: runtime.alloc_owned_plain(value),
46 runtime_id: runtime.id(),
47 _marker: PhantomData,
48 }
49 }
50
51 pub fn is_alive(&self) -> bool {
53 self.try_with(|_| ()).is_some()
54 }
55
56 pub fn try_get(&self) -> Option<Rc<T>> {
59 runtime::with_state_arena_by_id(self.runtime_id, |arena| arena.plain::<T>(self.id))?
60 }
61
62 pub fn get(&self) -> Rc<T> {
64 self.try_get()
65 .unwrap_or_else(|| panic!("runtime cell {:?} is no longer alive", self.id))
66 }
67
68 pub fn try_with<R>(&self, f: impl FnOnce(&T) -> R) -> Option<R> {
70 self.try_get().map(|value| f(&value))
71 }
72
73 pub fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
75 f(&self.get())
76 }
77}
78
79impl<T: 'static> Clone for RuntimeCell<T> {
80 fn clone(&self) -> Self {
81 *self
82 }
83}
84
85impl<T: 'static> Copy for RuntimeCell<T> {}
86
87impl<T: 'static> PartialEq for RuntimeCell<T> {
88 fn eq(&self, other: &Self) -> bool {
89 self.id == other.id && self.runtime_id == other.runtime_id
90 }
91}
92
93impl<T: 'static> Eq for RuntimeCell<T> {}
94
95impl<T: 'static> Hash for RuntimeCell<T> {
96 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
97 self.id.hash(state);
98 self.runtime_id.hash(state);
99 }
100}
101
102impl<T: 'static> fmt::Debug for RuntimeCell<T> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 f.debug_struct("RuntimeCell")
105 .field("id", &self.id)
106 .field("runtime_id", &self.runtime_id)
107 .finish()
108 }
109}