arena.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 pending_events = Rc::new(RefCell::new(Vec::new()));
  55. let (sender, receiver) = futures_channel::mpsc::unbounded();
  56. let heuristics = HeuristicsEngine::new();
  57. // we allocate this task setter once to save us from having to allocate later
  58. let task_setter = {
  59. let queue = sender.clone();
  60. let components = components.clone();
  61. Rc::new(move |idx: ScopeId| {
  62. let comps = unsafe { &*components.get() };
  63. if let Some(scope) = comps.get(idx.0) {
  64. queue
  65. .unbounded_send(EventTrigger::new(
  66. VirtualEvent::ScheduledUpdate {
  67. height: scope.height,
  68. },
  69. idx,
  70. None,
  71. EventPriority::High,
  72. ))
  73. .expect("The event queu receiver should *never* be dropped");
  74. }
  75. }) as Rc<dyn Fn(ScopeId)>
  76. };
  77. Self {
  78. components,
  79. async_tasks: Rc::new(RefCell::new(FuturesUnordered::new())),
  80. task_receiver: Rc::new(RefCell::new(receiver)),
  81. task_sender: sender,
  82. heuristics: Rc::new(RefCell::new(heuristics)),
  83. raw_elements: Rc::new(RefCell::new(raw_elements)),
  84. task_setter,
  85. }
  86. }
  87. /// this is unsafe because the caller needs to track which other scopes it's already using
  88. pub unsafe fn get_scope(&self, idx: ScopeId) -> Option<&Scope> {
  89. let inner = &*self.components.get();
  90. inner.get(idx.0)
  91. }
  92. /// this is unsafe because the caller needs to track which other scopes it's already using
  93. pub unsafe fn get_scope_mut(&self, idx: ScopeId) -> Option<&mut Scope> {
  94. let inner = &mut *self.components.get();
  95. inner.get_mut(idx.0)
  96. }
  97. pub fn with_scope<'b, O: 'static>(
  98. &'b self,
  99. _id: ScopeId,
  100. _f: impl FnOnce(&'b mut Scope) -> O,
  101. ) -> Result<O> {
  102. todo!()
  103. }
  104. // return a bumpframe with a lifetime attached to the arena borrow
  105. // this is useful for merging lifetimes
  106. pub fn with_scope_vnode<'b>(
  107. &self,
  108. _id: ScopeId,
  109. _f: impl FnOnce(&mut Scope) -> &VNode<'b>,
  110. ) -> Result<&VNode<'b>> {
  111. todo!()
  112. }
  113. pub fn try_remove(&self, id: ScopeId) -> Result<Scope> {
  114. let inner = unsafe { &mut *self.components.get() };
  115. Ok(inner.remove(id.0))
  116. // .try_remove(id.0)
  117. // .ok_or_else(|| Error::FatalInternal("Scope not found"))
  118. }
  119. pub fn reserve_node(&self) -> ElementId {
  120. ElementId(self.raw_elements.borrow_mut().insert(()))
  121. }
  122. /// return the id, freeing the space of the original node
  123. pub fn collect_garbage(&self, id: ElementId) {
  124. self.raw_elements.borrow_mut().remove(id.0);
  125. }
  126. pub fn insert_scope_with_key(&self, f: impl FnOnce(ScopeId) -> Scope) -> ScopeId {
  127. let g = unsafe { &mut *self.components.get() };
  128. let entry = g.vacant_entry();
  129. let id = ScopeId(entry.key());
  130. entry.insert(f(id));
  131. id
  132. }
  133. pub fn schedule_update(&self) -> Rc<dyn Fn(ScopeId)> {
  134. self.task_setter.clone()
  135. }
  136. pub fn submit_task(&self, task: FiberTask) -> TaskHandle {
  137. self.async_tasks.borrow_mut().push(task);
  138. TaskHandle {}
  139. }
  140. }
  141. pub struct TaskHandle {}
  142. impl TaskHandle {
  143. pub fn toggle(&self) {}
  144. pub fn start(&self) {}
  145. pub fn stop(&self) {}
  146. pub fn restart(&self) {}
  147. }