root.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
  2. use dioxus_core::ScopeId;
  3. use im_rc::HashSet;
  4. use crate::Readable;
  5. pub type AtomId = *const ();
  6. pub struct AtomRoot {
  7. pub atoms: RefCell<HashMap<AtomId, Slot>>,
  8. pub update_any: Arc<dyn Fn(ScopeId)>,
  9. }
  10. pub struct Slot {
  11. pub value: Rc<dyn Any>,
  12. pub subscribers: HashSet<ScopeId>,
  13. }
  14. impl AtomRoot {
  15. pub fn new(update_any: Arc<dyn Fn(ScopeId)>) -> Self {
  16. Self {
  17. update_any,
  18. atoms: RefCell::new(HashMap::new()),
  19. }
  20. }
  21. pub fn initialize<V: 'static>(&self, f: impl Readable<V>) {
  22. let id = f.unique_id();
  23. if self.atoms.borrow().get(&id).is_none() {
  24. self.atoms.borrow_mut().insert(
  25. id,
  26. Slot {
  27. value: Rc::new(f.init()),
  28. subscribers: HashSet::new(),
  29. },
  30. );
  31. }
  32. }
  33. pub fn register<V: 'static>(&self, f: impl Readable<V>, scope: ScopeId) -> Rc<V> {
  34. let mut atoms = self.atoms.borrow_mut();
  35. // initialize the value if it's not already initialized
  36. if let Some(slot) = atoms.get_mut(&f.unique_id()) {
  37. slot.subscribers.insert(scope);
  38. slot.value.clone().downcast().unwrap()
  39. } else {
  40. let value = Rc::new(f.init());
  41. let mut subscribers = HashSet::new();
  42. subscribers.insert(scope);
  43. atoms.insert(
  44. f.unique_id(),
  45. Slot {
  46. value: value.clone(),
  47. subscribers,
  48. },
  49. );
  50. value
  51. }
  52. }
  53. pub fn set<V: 'static>(&self, ptr: AtomId, value: V) {
  54. let mut atoms = self.atoms.borrow_mut();
  55. if let Some(slot) = atoms.get_mut(&ptr) {
  56. slot.value = Rc::new(value);
  57. log::trace!("found item with subscribers {:?}", slot.subscribers);
  58. for scope in &slot.subscribers {
  59. log::trace!("updating subcsriber");
  60. (self.update_any)(*scope);
  61. }
  62. } else {
  63. log::trace!("no atoms found for {:?}", ptr);
  64. atoms.insert(
  65. ptr,
  66. Slot {
  67. value: Rc::new(value),
  68. subscribers: HashSet::new(),
  69. },
  70. );
  71. }
  72. }
  73. pub fn unsubscribe(&self, ptr: AtomId, scope: ScopeId) {
  74. let mut atoms = self.atoms.borrow_mut();
  75. if let Some(slot) = atoms.get_mut(&ptr) {
  76. slot.subscribers.remove(&scope);
  77. }
  78. }
  79. // force update of all subscribers
  80. pub fn force_update(&self, ptr: AtomId) {
  81. if let Some(slot) = self.atoms.borrow_mut().get(&ptr) {
  82. for scope in slot.subscribers.iter() {
  83. log::trace!("updating subcsriber");
  84. (self.update_any)(*scope);
  85. }
  86. }
  87. }
  88. pub fn read<V: 'static>(&self, f: impl Readable<V>) -> Rc<V> {
  89. let mut atoms = self.atoms.borrow_mut();
  90. // initialize the value if it's not already initialized
  91. if let Some(slot) = atoms.get_mut(&f.unique_id()) {
  92. slot.value.clone().downcast().unwrap()
  93. } else {
  94. let value = Rc::new(f.init());
  95. atoms.insert(
  96. f.unique_id(),
  97. Slot {
  98. value: value.clone(),
  99. subscribers: HashSet::new(),
  100. },
  101. );
  102. value
  103. }
  104. }
  105. }