arena.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. use std::cell::{RefCell, RefMut};
  2. use std::fmt::Display;
  3. use std::{cell::UnsafeCell, rc::Rc};
  4. use crate::heuristics::*;
  5. use crate::innerlude::*;
  6. use futures_util::stream::FuturesUnordered;
  7. use fxhash::{FxHashMap, FxHashSet};
  8. use slab::Slab;
  9. use smallvec::SmallVec;
  10. // slotmap::new_key_type! {
  11. // // A dedicated key type for the all the scopes
  12. // pub struct ScopeId;
  13. // }
  14. // #[cfg(feature = "serialize", serde::Serialize)]
  15. // #[cfg(feature = "serialize", serde::Serialize)]
  16. #[derive(serde::Serialize, serde::Deserialize, Copy, Clone, PartialEq, Eq, Hash, Debug)]
  17. pub struct ScopeId(pub usize);
  18. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
  19. pub struct ElementId(pub usize);
  20. impl Display for ElementId {
  21. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  22. write!(f, "{}", self.0)
  23. }
  24. }
  25. impl ElementId {
  26. pub fn as_u64(self) -> u64 {
  27. self.0 as u64
  28. }
  29. }
  30. type Shared<T> = Rc<RefCell<T>>;
  31. type TaskReceiver = futures_channel::mpsc::UnboundedReceiver<EventTrigger>;
  32. type TaskSender = futures_channel::mpsc::UnboundedSender<EventTrigger>;
  33. /// These are resources shared among all the components and the virtualdom itself
  34. #[derive(Clone)]
  35. pub struct SharedResources {
  36. pub components: Rc<UnsafeCell<Slab<Scope>>>,
  37. pub(crate) heuristics: Shared<HeuristicsEngine>,
  38. ///
  39. pub task_sender: TaskSender,
  40. pub task_receiver: Shared<TaskReceiver>,
  41. pub async_tasks: Shared<FuturesUnordered<FiberTask>>,
  42. /// We use a SlotSet to keep track of the keys that are currently being used.
  43. /// However, we don't store any specific data since the "mirror"
  44. pub raw_elements: Rc<RefCell<Slab<()>>>,
  45. pub task_setter: Rc<dyn Fn(ScopeId)>,
  46. }
  47. impl SharedResources {
  48. pub fn new() -> Self {
  49. // preallocate 2000 elements and 20 scopes to avoid dynamic allocation
  50. let components: Rc<UnsafeCell<Slab<Scope>>> =
  51. Rc::new(UnsafeCell::new(Slab::with_capacity(100)));
  52. // elements are super cheap - the value takes no space
  53. let raw_elements = Slab::with_capacity(2000);
  54. let (sender, receiver) = futures_channel::mpsc::unbounded();
  55. let heuristics = HeuristicsEngine::new();
  56. // we allocate this task setter once to save us from having to allocate later
  57. let task_setter = {
  58. let queue = sender.clone();
  59. let components = components.clone();
  60. Rc::new(move |idx: ScopeId| {
  61. let comps = unsafe { &*components.get() };
  62. if let Some(scope) = comps.get(idx.0) {
  63. queue
  64. .unbounded_send(EventTrigger::new(
  65. VirtualEvent::ScheduledUpdate {
  66. height: scope.height,
  67. },
  68. idx,
  69. None,
  70. EventPriority::High,
  71. ))
  72. .expect("The event queu receiver should *never* be dropped");
  73. }
  74. }) as Rc<dyn Fn(ScopeId)>
  75. };
  76. Self {
  77. components,
  78. async_tasks: Rc::new(RefCell::new(FuturesUnordered::new())),
  79. task_receiver: Rc::new(RefCell::new(receiver)),
  80. task_sender: sender,
  81. heuristics: Rc::new(RefCell::new(heuristics)),
  82. raw_elements: Rc::new(RefCell::new(raw_elements)),
  83. task_setter,
  84. }
  85. }
  86. /// this is unsafe because the caller needs to track which other scopes it's already using
  87. pub fn get_scope(&self, idx: ScopeId) -> Option<&Scope> {
  88. let inner = unsafe { &*self.components.get() };
  89. inner.get(idx.0)
  90. }
  91. /// this is unsafe because the caller needs to track which other scopes it's already using
  92. pub fn get_scope_mut(&self, idx: ScopeId) -> Option<&mut Scope> {
  93. let inner = unsafe { &mut *self.components.get() };
  94. inner.get_mut(idx.0)
  95. }
  96. pub fn with_scope<'b, O: 'static>(
  97. &'b self,
  98. _id: ScopeId,
  99. _f: impl FnOnce(&'b mut Scope) -> O,
  100. ) -> Result<O> {
  101. todo!()
  102. }
  103. // return a bumpframe with a lifetime attached to the arena borrow
  104. // this is useful for merging lifetimes
  105. pub fn with_scope_vnode<'b>(
  106. &self,
  107. _id: ScopeId,
  108. _f: impl FnOnce(&mut Scope) -> &VNode<'b>,
  109. ) -> Result<&VNode<'b>> {
  110. todo!()
  111. }
  112. pub fn try_remove(&self, id: ScopeId) -> Result<Scope> {
  113. let inner = unsafe { &mut *self.components.get() };
  114. Ok(inner.remove(id.0))
  115. // .try_remove(id.0)
  116. // .ok_or_else(|| Error::FatalInternal("Scope not found"))
  117. }
  118. pub fn reserve_node(&self) -> ElementId {
  119. ElementId(self.raw_elements.borrow_mut().insert(()))
  120. }
  121. /// return the id, freeing the space of the original node
  122. pub fn collect_garbage(&self, id: ElementId) {
  123. self.raw_elements.borrow_mut().remove(id.0);
  124. }
  125. pub fn insert_scope_with_key(&self, f: impl FnOnce(ScopeId) -> Scope) -> ScopeId {
  126. let g = unsafe { &mut *self.components.get() };
  127. let entry = g.vacant_entry();
  128. let id = ScopeId(entry.key());
  129. entry.insert(f(id));
  130. id
  131. }
  132. pub fn schedule_update(&self) -> Rc<dyn Fn(ScopeId)> {
  133. self.task_setter.clone()
  134. }
  135. pub fn submit_task(&self, task: FiberTask) -> TaskHandle {
  136. self.async_tasks.borrow_mut().push(task);
  137. TaskHandle {}
  138. }
  139. pub fn make_trigger_key(&self, trigger: &EventTrigger) -> EventKey {
  140. let height = self
  141. .get_scope(trigger.originator)
  142. .map(|f| f.height)
  143. .unwrap();
  144. EventKey {
  145. height,
  146. originator: trigger.originator,
  147. priority: trigger.priority,
  148. }
  149. }
  150. }
  151. pub struct TaskHandle {}
  152. impl TaskHandle {
  153. pub fn toggle(&self) {}
  154. pub fn start(&self) {}
  155. pub fn stop(&self) {}
  156. pub fn restart(&self) {}
  157. }