lib.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. use std::{
  2. cell::{Ref, RefCell, RefMut},
  3. rc::Rc,
  4. sync::Arc,
  5. };
  6. mod rt;
  7. pub use rt::*;
  8. mod effect;
  9. pub use effect::*;
  10. #[macro_use]
  11. mod impls;
  12. use dioxus_core::{
  13. prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
  14. ScopeId, ScopeState,
  15. };
  16. pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
  17. *cx.use_hook(|| Signal::new(f()))
  18. }
  19. #[derive(Clone)]
  20. struct Unsubscriber {
  21. scope: ScopeId,
  22. subscribers: Rc<RefCell<Vec<Rc<RefCell<Vec<ScopeId>>>>>>,
  23. }
  24. impl Drop for Unsubscriber {
  25. fn drop(&mut self) {
  26. for subscribers in self.subscribers.borrow().iter() {
  27. subscribers.borrow_mut().retain(|s| *s != self.scope);
  28. }
  29. }
  30. }
  31. fn current_unsubscriber() -> Unsubscriber {
  32. match has_context() {
  33. Some(rt) => rt,
  34. None => {
  35. let owner = Unsubscriber {
  36. scope: current_scope_id().expect("in a virtual dom"),
  37. subscribers: Default::default(),
  38. };
  39. provide_context(owner).expect("in a virtual dom")
  40. }
  41. }
  42. }
  43. struct SignalData<T> {
  44. subscribers: Rc<RefCell<Vec<ScopeId>>>,
  45. effect_subscribers: Rc<RefCell<Vec<Effect>>>,
  46. update_any: Arc<dyn Fn(ScopeId)>,
  47. value: T,
  48. }
  49. pub struct Signal<T: 'static> {
  50. inner: CopyValue<SignalData<T>>,
  51. }
  52. impl<T: 'static> Signal<T> {
  53. pub fn new(value: T) -> Self {
  54. Self {
  55. inner: CopyValue::new(SignalData {
  56. subscribers: Default::default(),
  57. effect_subscribers: Default::default(),
  58. update_any: schedule_update_any().expect("in a virtual dom"),
  59. value,
  60. }),
  61. }
  62. }
  63. pub fn read(&self) -> Ref<T> {
  64. let inner = self.inner.read();
  65. if let Some(current_scope_id) = current_scope_id() {
  66. let mut subscribers = inner.subscribers.borrow_mut();
  67. if !subscribers.contains(&current_scope_id) {
  68. subscribers.push(current_scope_id);
  69. drop(subscribers);
  70. let unsubscriber = current_unsubscriber();
  71. inner.subscribers.borrow_mut().push(unsubscriber.scope);
  72. }
  73. }
  74. if let Some(effect) = Effect::current() {
  75. let mut effect_subscribers = inner.effect_subscribers.borrow_mut();
  76. if !effect_subscribers.contains(&effect) {
  77. effect_subscribers.push(effect);
  78. }
  79. }
  80. Ref::map(inner, |v| &v.value)
  81. }
  82. pub fn write(&self) -> RefMut<T> {
  83. {
  84. let inner = self.inner.read();
  85. for &scope_id in &*inner.subscribers.borrow() {
  86. (inner.update_any)(scope_id);
  87. }
  88. }
  89. let subscribers =
  90. { std::mem::take(&mut *self.inner.read().effect_subscribers.borrow_mut()) };
  91. for effect in subscribers {
  92. effect.try_run();
  93. }
  94. let inner = self.inner.write();
  95. RefMut::map(inner, |v| &mut v.value)
  96. }
  97. pub fn set(&mut self, value: T) {
  98. *self.write() = value;
  99. }
  100. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  101. let write = self.read();
  102. f(&*write)
  103. }
  104. pub fn with_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
  105. let mut write = self.write();
  106. f(&mut *write)
  107. }
  108. }
  109. impl<T: Clone + 'static> Signal<T> {
  110. pub fn value(&self) -> T {
  111. self.read().clone()
  112. }
  113. }
  114. impl<T: 'static> PartialEq for Signal<T> {
  115. fn eq(&self, other: &Self) -> bool {
  116. self.inner == other.inner
  117. }
  118. }