1use std::{
2 ops::{Deref, DerefMut},
3 rc::Rc,
4 sync::Arc,
5};
6
7use parking_lot::{Mutex, MutexGuard};
8
9use crate::{id::Id, signal::TrackedRefCell};
10
11pub struct SyncWriteRef<'a, T> {
12 id: Id,
13 _handle: Arc<Mutex<T>>,
14 pub(crate) guard: Option<MutexGuard<'a, T>>,
15}
16
17pub struct LocalWriteRef<'a, T> {
18 id: Id,
19 _handle: Rc<TrackedRefCell<T>>,
20 pub(crate) guard: Option<crate::signal::TrackedRefMut<'a, T>>,
21}
22
23pub enum WriteRef<'a, T> {
24 Sync(SyncWriteRef<'a, T>),
25 Local(LocalWriteRef<'a, T>),
26}
27
28impl<'a, T> SyncWriteRef<'a, T> {
29 pub(crate) fn new(id: Id, handle: Arc<Mutex<T>>) -> Self {
30 let guard = handle.lock();
31 let guard = unsafe { std::mem::transmute::<MutexGuard<'_, T>, MutexGuard<'a, T>>(guard) };
32 Self {
33 id,
34 _handle: handle,
35 guard: Some(guard),
36 }
37 }
38}
39
40impl<'a, T> Drop for SyncWriteRef<'a, T> {
41 fn drop(&mut self) {
42 if let Some(guard) = self.guard.take() {
43 drop(guard);
44 }
45 if let Some(signal) = self.id.signal() {
46 signal.run_effects();
47 }
48 }
49}
50
51impl<'a, T> LocalWriteRef<'a, T> {
52 pub(crate) fn new(id: Id, handle: Rc<TrackedRefCell<T>>) -> Self {
53 let guard = handle.borrow_mut();
54 let guard = unsafe {
55 std::mem::transmute::<
56 crate::signal::TrackedRefMut<'_, T>,
57 crate::signal::TrackedRefMut<'a, T>,
58 >(guard)
59 };
60 Self {
61 id,
62 _handle: handle,
63 guard: Some(guard),
64 }
65 }
66}
67
68impl<'a, T> Drop for LocalWriteRef<'a, T> {
69 fn drop(&mut self) {
70 if let Some(guard) = self.guard.take() {
71 drop(guard);
72 }
73 if let Some(signal) = self.id.signal() {
74 signal.run_effects();
75 }
76 }
77}
78
79impl<'a, T> Deref for WriteRef<'a, T> {
80 type Target = T;
81 fn deref(&self) -> &Self::Target {
82 match self {
83 WriteRef::Sync(v) => v.guard.as_ref().expect("guard present"),
84 WriteRef::Local(v) => v.guard.as_ref().expect("guard present"),
85 }
86 }
87}
88
89impl<'a, T> DerefMut for WriteRef<'a, T> {
90 fn deref_mut(&mut self) -> &mut Self::Target {
91 match self {
92 WriteRef::Sync(v) => &mut *v.guard.as_mut().expect("guard present"),
93 WriteRef::Local(v) => &mut *v.guard.as_mut().expect("guard present"),
94 }
95 }
96}
97
98pub trait SignalUpdate<T> {
99 fn id(&self) -> Id;
101
102 fn set(&self, new_value: T)
104 where
105 T: 'static,
106 {
107 let _ = self.try_update(|v| *v = new_value);
108 }
109
110 fn update(&self, f: impl FnOnce(&mut T))
112 where
113 T: 'static,
114 {
115 let _ = self.try_update(f);
116 }
117
118 fn try_update<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O>
121 where
122 T: 'static;
123}
124
125pub trait SignalWrite<T> {
126 fn id(&self) -> Id;
128 fn write(&self) -> WriteRef<'_, T>
130 where
131 T: 'static,
132 {
133 self.try_write().unwrap()
134 }
135
136 fn try_write(&self) -> Option<WriteRef<'_, T>>
138 where
139 T: 'static;
140}