render_signal.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. //! In dioxus, effects are run using normal async functions after a render. [RenderSignalFuture] is a future that resolves after a render has passed.
  2. use std::cell::RefCell;
  3. use std::future::Future;
  4. use std::pin::Pin;
  5. use std::rc::Rc;
  6. use std::task::Context;
  7. use std::task::Poll;
  8. use std::task::Waker;
  9. /// A signal is a message that can be sent to all listening tasks at once
  10. #[derive(Default)]
  11. pub struct RenderSignal {
  12. wakers: Rc<RefCell<Vec<Rc<RefCell<RenderSignalFutureInner>>>>>,
  13. }
  14. impl RenderSignal {
  15. /// Send the signal to all listening tasks
  16. pub fn send(&self) {
  17. let mut wakers = self.wakers.borrow_mut();
  18. for waker in wakers.drain(..) {
  19. let mut inner = waker.borrow_mut();
  20. inner.resolved = true;
  21. if let Some(waker) = inner.waker.take() {
  22. waker.wake();
  23. }
  24. }
  25. }
  26. /// Create a future that resolves when the signal is sent
  27. pub fn subscribe(&self) -> RenderSignalFuture {
  28. let inner = Rc::new(RefCell::new(RenderSignalFutureInner {
  29. resolved: false,
  30. waker: None,
  31. }));
  32. self.wakers.borrow_mut().push(inner.clone());
  33. RenderSignalFuture { inner }
  34. }
  35. }
  36. struct RenderSignalFutureInner {
  37. resolved: bool,
  38. waker: Option<Waker>,
  39. }
  40. pub(crate) struct RenderSignalFuture {
  41. inner: Rc<RefCell<RenderSignalFutureInner>>,
  42. }
  43. impl Future for RenderSignalFuture {
  44. type Output = ();
  45. fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
  46. let mut inner = self.inner.borrow_mut();
  47. if inner.resolved {
  48. Poll::Ready(())
  49. } else {
  50. inner.waker = Some(cx.waker().clone());
  51. Poll::Pending
  52. }
  53. }
  54. }