duat_core/
data.rs

1//! Duat's way of sharing and updating state
2//!
3//! This module consists primarily of the [`RwData`] struct, which
4//! holds state that can be [read] or [written to]. When it is
5//! modified, other holders of a clone of [`RwData`] will know that
6//! the data within has been modified.
7//!
8//! This is used in many places, for example, [`Widget`]s can read
9//! from [`Buffer`]s, and Duat can know when a [`Buffer`] has been
10//! altered, so these [`Widget`]s may be [updated] automatically.
11//!
12//! Another struct from this module is [`DataMap`]. This is
13//! essentially a mapping for a [`RwData`]. It is created via
14//! [`RwData::map`], and both it and [`RwData`] can be very useful in,
15//! for example, a [`StatusLine`], since it will be updated
16//! automatically whenever the [`RwData`] is altered.
17//!
18//! One thing to note is that these structs are only meant to exist
19//! and be used in the main thread of execution in Duat. In fact, it
20//! should be impossible to acquire them outside of this main thread
21//! without use of unsafe code. If it is still possible, report that
22//! as a bug.
23//!
24//! The reason why these structs should only be valid in the main
25//! thread is because, internally, they use non [`Send`]/[`Sync`]
26//! structs, specifically [`RefCell`] and [`UnsafeCell`].
27//! These are often considered "crutches" by a lot of the Rust
28//! community, but in an environment where most of the code is
29//! supposed to be able to access most of the state, it is impossible
30//! to go without using them.
31//!
32//! The use of [`UnsafeCell`] internally also makes the [`read`] and
33//! [`write`] operations _basically_ 0 cost,
34//!
35//! [read]: RwData::read
36//! [written to]: RwData::write
37//! [`Widget`]: crate::ui::Widget
38//! [`Buffer`]: crate::buffer::Buffer
39//! [updated]: crate::ui::Widget::update
40//! [`Text`]: crate::text::Text
41//! [`StatusLine`]: https://docs.rs/duat/latest/duat/widgets/struct.StatusLine.html
42//! [`context`]: crate::context
43//! [`Mutex`]: std::sync::Mutex
44//! [`read`]: RwData::read
45//! [`write`]: RwData::write
46use std::{
47    self,
48    any::TypeId,
49    cell::{RefCell, UnsafeCell},
50    marker::PhantomData,
51    sync::{
52        Arc, LazyLock, Mutex,
53        atomic::{AtomicBool, AtomicUsize, Ordering},
54    },
55    time::Duration,
56};
57
58use crate::ui::Widget;
59
60/// A container for shared read/write state
61///
62/// This is the struct used internally (and externally) to allow for
63/// massively shareable state in duat's API. Its main purpose is to
64/// hold all of the [`Widget`]s in Duat, making them available for
65/// usage from any function with access to a [`Pass`]. However, it can
66/// also be used to hold any other type, and also has the ability to
67/// notify when changes have taken place.
68///
69/// # [`Pass`]es
70///
71/// The `Pass` is a sort of "key" for accessing the value within an
72/// `RwData`, its purpose is to maintain Rust's number one rule,
73/// i.e. one exclusive reference or multiple shared references
74/// (mutability XOR aliasing), and that is done by borrowing the
75/// `Pass` mutably or non mutably. That comes with some limitations
76/// on how they can be used, mostly the fact that you must mutably
77/// borrow all `RwData`s that will be used [_at the same time_] in
78/// order to get multiple mutable references at once.
79///
80/// The use of a `Pass` for reading/writing to `RwData`s confers
81/// various benefits:
82///
83/// - Aside from updating an internal update counter, it is truly
84///   _zero cost_, unlike in the case of a [`Mutex`] or [`RefCell`],
85///   which have to do checks at runtime. This happens because the
86///   `Pass` has zero size, i.e. it gets removed at compile time.
87/// - You can't run into deadlocks like you would be able to when
88///   using `Mutex`es. Neither can you run into panics from
89///   reborrowing, like with `RefCell`.
90/// - You don't have to drop a `Guard` type (like [`MutexGuard`]) in
91///   order to reborrow from the `RwData` since borrowing gives you a
92///   first class `&` or `&mut`, which are much easier to work with.
93/// - You can do sub borrowings, like `&mut data.write(pa).field`,
94///   given the `&mut` borrow.
95///
96/// However, there are also a few disadvantages:
97///
98/// - Sometimes, mutably borrowing multiple things in a single
99///   function _can_ be a challenge, although that is mostly mitigated
100///   by [`Pass::write_many`].
101/// - You _cannot_ access the data in a `RwData` from threads other
102///   than the main one, since the `Pass` is only accessible from it.
103///   This isn't _really_ a disadvantage, since it simplifies thought
104///   patterns and eases reasoning about the current state of things.
105///
106/// [`Mutex`]: std::sync::Mutex
107/// [`MutexGuard`]: std::sync::MutexGuard
108/// [parser]: crate::buffer::BufferTracker
109/// [`Text`]: crate::text::Text
110/// [_at the same time_]: Pass::write_many
111#[derive(Debug)]
112pub struct RwData<T: ?Sized> {
113    value: Arc<UnsafeCell<T>>,
114    cur_state: Arc<AtomicUsize>,
115    read_state: Arc<AtomicUsize>,
116    ty: TypeId,
117}
118
119impl<T: 'static> RwData<T> {
120    /// Returns a new [`RwData<T>`]
121    ///
122    /// Note that this is only for sized types. For unsized types, the
123    /// process is a little more convoluted, and you need to use
124    /// [`RwData::new_unsized`].
125    pub fn new(value: T) -> Self {
126        Self {
127            value: Arc::new(UnsafeCell::new(value)),
128            ty: TypeId::of::<T>(),
129            cur_state: Arc::new(AtomicUsize::new(1)),
130            read_state: Arc::new(AtomicUsize::new(0)),
131        }
132    }
133}
134
135impl<T: ?Sized> RwData<T> {
136    /// Returns an unsized [`RwData`], such as [`RwData<dyn Trait>`]
137    ///
138    /// # Safety
139    ///
140    /// There is a type argument `SizedT` which _must_ be the exact
141    /// type you are passing to this constructor, i.e., if you are
142    /// creating an [`RwData<dyn Display>`] from a [`String`], you'd
143    /// do this:
144    ///
145    /// ```rust
146    /// # duat_core::doc_duat!(duat);
147    /// use std::{cell::UnsafeCell, fmt::Display, sync::Arc};
148    ///
149    /// use duat::{data::RwData, prelude::*};
150    /// let rw_data: RwData<dyn Display> =
151    ///     unsafe { RwData::new_unsized::<String>(Arc::new(UnsafeCell::new("test".to_string()))) };
152    /// ```
153    ///
154    /// This ensures that methods such as [`read_as`] and [`write_as`]
155    /// will correctly identify such [`RwData<dyn Display>`] as a
156    /// [`String`].
157    ///
158    /// [`read_as`]: Self::read_as
159    /// [`write_as`]: Self::write_as
160    #[doc(hidden)]
161    pub unsafe fn new_unsized<SizedT: 'static>(value: Arc<UnsafeCell<T>>) -> Self {
162        Self {
163            value,
164            ty: TypeId::of::<SizedT>(),
165            cur_state: Arc::new(AtomicUsize::new(1)),
166            read_state: Arc::new(AtomicUsize::new(0)),
167        }
168    }
169
170    ////////// Reading functions
171
172    /// Reads the value within using a [`Pass`]
173    ///
174    /// The consistent use of a [`Pass`] for the purposes of
175    /// reading/writing to the values of [`RwData`]s ensures that no
176    /// panic or invalid borrow happens at runtime, even while working
177    /// with untrusted code. More importantly, Duat uses these
178    /// guarantees in order to give the end user a ridiculous amount
179    /// of freedom in where they can do things, whilst keeping Rust's
180    /// number one rule and ensuring thread safety, even with a
181    /// relatively large amount of shareable state.
182    pub fn read<'p>(&'p self, _: &'p Pass) -> &'p T {
183        self.read_state
184            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
185        // SAFETY: If one were to try and write to this value, this reference
186        // would instantly become invalid, and trying to read from it again
187        // would cause a compile error due to a Pass borrowing conflict.
188        unsafe { &*self.value.get() }
189    }
190
191    /// Reads the value within as `U` using a [`Pass`]
192    ///
193    /// The consistent use of a [`Pass`] for the purposes of
194    /// reading/writing to the values of [`RwData`]s ensures that no
195    /// panic or invalid borrow happens at runtime, even while working
196    /// with untrusted code. More importantly, Duat uses these
197    /// guarantees in order to give the end user a ridiculous amount
198    /// of freedom in where they can do things, whilst keeping Rust's
199    /// number one rule and ensuring thread safety, even with a
200    /// relatively large amount of shareable state.
201    pub fn read_as<'p, U: 'static>(&'p self, _: &'p Pass) -> Option<&'p U> {
202        if TypeId::of::<U>() != self.ty {
203            return None;
204        }
205
206        self.read_state
207            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
208
209        let ptr = Arc::as_ptr(&self.value) as *const UnsafeCell<U>;
210
211        // SAFETY: Same as above, but also, the TypeId in the Handle
212        // "guarantees" that this is the correct type.
213        Some(unsafe { &*(&*ptr).get() })
214    }
215
216    /// Simulates a [`read`] without actually reading
217    ///
218    /// This is useful if you want to tell Duat that you don't want
219    /// [`has_changed`] to return `true`, but you don't have a
220    /// [`Pass`] available to [`read`] the value.
221    ///
222    /// [`read`]: Self::read
223    /// [`has_changed`]: Self::has_changed
224    pub fn declare_as_read(&self) {
225        self.read_state
226            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
227    }
228
229    ////////// Writing functions
230
231    /// Writes to the value within using a [`Pass`]
232    ///
233    /// The consistent use of a [`Pass`] for the purposes of
234    /// reading/writing to the values of [`RwData`]s ensures that no
235    /// panic or invalid borrow happens at runtime, even while working
236    /// with untrusted code. More importantly, Duat uses these
237    /// guarantees in order to give the end user a ridiculous amount
238    /// of freedom in where they can do things, whilst keeping Rust's
239    /// number one rule and ensuring thread safety, even with a
240    /// relatively large amount of shareable state.
241    pub fn write<'p>(&'p self, _: &'p mut Pass) -> &'p mut T {
242        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
243        self.read_state.store(prev + 1, Ordering::Relaxed);
244        // SAFETY: Again, the mutable reference to the Pass ensures that this
245        // is the only _valid_ mutable reference, if another reference,
246        // created prior to this one, were to be reused, that would be a
247        // compile error.
248        unsafe { &mut *self.value.get() }
249    }
250
251    /// Writes to the value within as `U` using a [`Pass`]
252    ///
253    /// The consistent use of a [`Pass`] for the purposes of
254    /// reading/writing to the values of [`RwData`]s ensures that no
255    /// panic or invalid borrow happens at runtime, even while working
256    /// with untrusted code. More importantly, Duat uses these
257    /// guarantees in order to give the end user a ridiculous amount
258    /// of freedom in where they can do things, whilst keeping Rust's
259    /// number one rule and ensuring thread safety, even with a
260    /// relatively large amount of shareable state.
261    pub fn write_as<'p, U: 'static>(&'p self, _: &'p mut Pass) -> Option<&'p mut U> {
262        if TypeId::of::<U>() != self.ty {
263            return None;
264        }
265
266        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
267        self.read_state.store(prev + 1, Ordering::Relaxed);
268
269        let ptr = Arc::as_ptr(&self.value) as *const UnsafeCell<U>;
270
271        // SAFETY: Same as above, but also, the TypeId in the Handle
272        // "guarantees" that this is the correct type.
273        Some(unsafe { &mut *(&*ptr).get() })
274    }
275
276    /// Writes to the value _and_ internal [`RwData`]-like structs
277    ///
278    /// This method takes a function that borrows a [`WriteableTuple`]
279    /// from `self`, letting you write to `self` and the data in the
280    /// tuple (or single element) at the same time.
281    ///
282    /// This is _really_ useful in a scenario where, for example, your
283    /// [`Handle<W>`] for some widget `W` holds a [`Handle<Buffer>`],
284    /// and you wish to access both at the same time, while writing to
285    /// the former:
286    ///
287    /// ```rust
288    /// # duat_core::doc_duat!(duat);
289    /// use duat::prelude::*;
290    ///
291    /// struct MyWidget {
292    ///     text: Text,
293    ///     buf: Handle,
294    /// }
295    ///
296    /// impl Widget for MyWidget {
297    ///     fn update(pa: &mut Pass, handle: &Handle<Self>) {
298    ///         let (wid, buf) = handle.write_then(pa, |wid| &wid.buf);
299    ///         // Updating the widget and reading/writing from the Buffer at the same time.
300    ///         // ...
301    ///     }
302    ///     // ..
303    ///     # fn text(&self) -> &Text { &self.text }
304    ///     # fn text_mut(&mut self) -> TextMut { self.text.as_mut() }
305    ///     # fn needs_update(&self, pa: &Pass) -> bool { false }
306    /// }
307    /// ```
308    ///
309    /// You can also return tuples from the function, allowing for
310    /// access to up to twelve different [`RwData`]-like structs:
311    ///
312    /// ```rust
313    /// # duat_core::doc_duat!(duat);
314    /// use duat::prelude::*;
315    ///
316    /// struct MyWidget {
317    ///     text: Text,
318    ///     buf1: Handle,
319    ///     buf2: Handle,
320    /// }
321    ///
322    /// impl Widget for MyWidget {
323    ///     fn update(pa: &mut Pass, handle: &Handle<Self>) {
324    ///         let (wid, (b1, b2)) = handle.write_then(pa, |wid| (&wid.buf1, &wid.buf2));
325    ///         // ...
326    ///     }
327    ///     // ..
328    ///     # fn text(&self) -> &Text { &self.text }
329    ///     # fn text_mut(&mut self) -> TextMut { self.text.as_mut() }
330    ///     # fn needs_update(&self, pa: &Pass) -> bool { false }
331    /// }
332    /// ```
333    ///
334    /// # Panics
335    ///
336    /// This function will panic if any of the elements of the tuple
337    /// point to the same data as any other element or `self`, see
338    /// [`Pass::write_many`] for more information.
339    ///
340    /// [`Handle<W>`]: crate::context::Handle
341    /// [`Handle<Buffer>`]: crate::context::Handle
342    #[track_caller]
343    #[allow(static_mut_refs)]
344    pub fn write_then<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
345        &'p self,
346        pa: &'p mut Pass,
347        tup_fn: impl FnOnce(&'p T) -> Tup,
348    ) -> (&'p mut T, Tup::Return) {
349        let tup = tup_fn(self.read(pa));
350        if tup
351            .state_ptrs()
352            .into_iter()
353            .any(|ptr| ptr == CurStatePtr(&self.cur_state))
354        {
355            panic!("Tried writing to the same data multiple times at the same time");
356        }
357
358        /// SAFETY: The ptrs are already verifiably not pointing to
359        /// the data of self.
360        static PASS: Pass = unsafe { Pass::new() };
361
362        let tup_ret = unsafe { (&raw const PASS as *mut Pass).as_mut() }
363            .unwrap()
364            .write_many(tup);
365
366        let value = self.write(unsafe { (&raw const PASS as *mut Pass).as_mut() }.unwrap());
367
368        (value, tup_ret)
369    }
370
371    /// Simulates a [`write`] without actually writing
372    ///
373    /// This is useful if you want to tell Duat that you want
374    /// [`has_changed`] to return `true`, but you don't have a
375    /// [`Pass`] available to [`write`] the value with.
376    ///
377    /// [`write`]: Self::write
378    /// [`has_changed`]: Self::has_changed
379    pub fn declare_written(&self) {
380        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
381        self.read_state.store(prev + 1, Ordering::Relaxed);
382    }
383
384    /// Takes the value within, replacing it with the default
385    pub fn take(&self, pa: &mut Pass) -> T
386    where
387        T: Default,
388    {
389        std::mem::take(self.write(pa))
390    }
391
392    ////////// Mapping of the inner value
393
394    /// Maps the value to another value with a function
395    ///
396    /// This function will return a struct that acts like a "read
397    /// only" version of [`RwData`], which also maps the value to
398    /// a return type.
399    pub fn map<Ret: 'static>(&self, map: impl FnMut(&T) -> Ret + 'static) -> DataMap<T, Ret> {
400        let RwData { value, cur_state, .. } = self.clone();
401        let data = RwData {
402            value,
403            cur_state,
404            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed))),
405            ty: TypeId::of::<T>(),
406        };
407
408        DataMap { data, map: Arc::new(RefCell::new(map)) }
409    }
410
411    /// Maps the value to another value with a mutating function
412    ///
413    /// This is useful if you want to repeat a function over and over
414    /// again in order to get a new different result, whilst mutating
415    /// the data within.
416    pub fn map_mut<Ret: 'static>(
417        &self,
418        map: impl FnMut(&mut T) -> Ret + 'static,
419    ) -> MutDataMap<T, Ret> {
420        let RwData { value, cur_state, .. } = self.clone();
421        let data = RwData {
422            value,
423            cur_state,
424            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed))),
425            ty: TypeId::of::<T>(),
426        };
427
428        MutDataMap { data, map: Arc::new(RefCell::new(map)) }
429    }
430
431    /// Attempts to downcast an [`RwData`] to a concrete type
432    ///
433    /// Returns [`Some(RwData<U>)`] if the value within is of type
434    /// `U`. For unsized types, `U` is the type parameter
435    /// passed when calling [`RwData::new_unsized`].
436    ///
437    /// [`Some(RwData<U>)`]: Some
438    pub fn try_downcast<U: 'static>(&self) -> Option<RwData<U>> {
439        if TypeId::of::<U>() != self.ty {
440            return None;
441        }
442
443        let ptr = Arc::into_raw(self.value.clone());
444        // SAFETY: TypeId argument "guarantees" this
445        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<U>) };
446        Some(RwData {
447            value,
448            cur_state: self.cur_state.clone(),
449            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
450            ty: TypeId::of::<U>(),
451        })
452    }
453
454    ////////// Querying functions
455
456    /// Wether this [`RwData`] and another point to the same value
457    pub fn ptr_eq<U: ?Sized>(&self, other: &RwData<U>) -> bool {
458        Arc::ptr_eq(&self.cur_state, &other.cur_state)
459    }
460
461    /// The [`TypeId`] of the concrete type within
462    pub fn type_id(&self) -> TypeId {
463        self.ty
464    }
465
466    /// Wether the concrete [`TypeId`] matches that of `U`
467    pub fn is<U: 'static>(&self) -> bool {
468        self.ty == TypeId::of::<U>()
469    }
470
471    /// Wether someone else called [`write`] or [`write_as`] since the
472    /// last [`read`] or `write`
473    ///
474    /// Do note that this *DOES NOT* mean that the value inside has
475    /// actually been changed, it just means a mutable reference was
476    /// acquired after the last call to [`has_changed`].
477    ///
478    /// Some types like [`Text`], and traits like [`Widget`] offer
479    /// [`has_changed`](crate::ui::Widget::needs_update) methods,
480    /// you should try to determine what parts to look for changes.
481    ///
482    /// Generally though, you can use this method to gauge that.
483    ///
484    /// [`write`]: Self::write
485    /// [`write_as`]: Self::write_as
486    /// [`read`]: Self::read
487    /// [`has_changed`]: Self::has_changed
488    /// [`Text`]: crate::text::Text
489    /// [`Widget`]: crate::ui::Widget
490    pub fn has_changed(&self) -> bool {
491        self.read_state.load(Ordering::Relaxed) < self.cur_state.load(Ordering::Relaxed)
492    }
493
494    /// A function that checks if the data has been updated
495    ///
496    /// Do note that this function will check for the specific
497    /// [`RwData`] that was used in its creation, so if you call
498    /// [`read`] on that specific [`RwData`] for example, this
499    /// function will start returning `false`.
500    ///
501    /// [`read`]: Self::read
502    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
503        let (read, cur) = (self.read_state.clone(), self.cur_state.clone());
504        move || read.load(Ordering::Relaxed) < cur.load(Ordering::Relaxed)
505    }
506}
507
508impl<W: Widget> RwData<W> {
509    /// Downcasts [`RwData<impl Widget>`] to [`RwData<dyn Widget>`]
510    pub fn to_dyn_widget(&self) -> RwData<dyn Widget> {
511        let ptr = Arc::into_raw(self.value.clone());
512        // SAFETY: Implements Widget
513        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<dyn Widget>) };
514        RwData {
515            value,
516            cur_state: self.cur_state.clone(),
517            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
518            ty: self.ty,
519        }
520    }
521}
522
523// SAFETY: The only parts that are accessible from other threads are
524// the atomic counters from the Arcs. Everything else can only be
525// acquired when there is a Pass, i.e., on the main thread.
526unsafe impl<T: ?Sized> Send for RwData<T> {}
527unsafe impl<T: ?Sized> Sync for RwData<T> {}
528
529impl<T: ?Sized> Clone for RwData<T> {
530    fn clone(&self) -> Self {
531        Self {
532            value: self.value.clone(),
533            ty: self.ty,
534            cur_state: self.cur_state.clone(),
535            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
536        }
537    }
538}
539
540impl<T: Default + 'static> Default for RwData<T> {
541    fn default() -> Self {
542        Self {
543            value: Arc::default(),
544            cur_state: Arc::new(AtomicUsize::new(1)),
545            read_state: Arc::new(AtomicUsize::new(0)),
546            ty: TypeId::of::<T>(),
547        }
548    }
549}
550
551/// A mapping of an [`RwData`]
552pub struct DataMap<I: ?Sized + 'static, O: 'static> {
553    data: RwData<I>,
554    map: Arc<RefCell<dyn FnMut(&I) -> O>>,
555}
556
557impl<I: ?Sized, O> DataMap<I, O> {
558    /// Call this `DataMap`'s mapping function, returning the output
559    pub fn call(&self, pa: &Pass) -> O {
560        self.map.borrow_mut()(self.data.read(pa))
561    }
562
563    /// Maps the value within, works just like [`RwData::map`]
564    pub fn map<O2>(self, mut f: impl FnMut(O) -> O2 + 'static) -> DataMap<I, O2> {
565        self.data.map(move |input| f(self.map.borrow_mut()(input)))
566    }
567
568    /// Wether someone else called [`write`] or [`write_as`] since the
569    /// last [`read`] or [`write`]
570    ///
571    /// Do note that this *DOES NOT* mean that the value inside has
572    /// actually been changed, it just means a mutable reference was
573    /// acquired after the last call to [`has_changed`].
574    ///
575    /// Some types like [`Text`], and traits like [`Widget`] offer
576    /// [`needs_update`] methods, you should try to determine what
577    /// parts to look for changes.
578    ///
579    /// Generally though, you can use this method to gauge that.
580    ///
581    /// [`write`]: RwData::write
582    /// [`write_as`]: RwData::write_as
583    /// [`read`]: RwData::read
584    /// [`has_changed`]: RwData::has_changed
585    /// [`Text`]: crate::text::Text
586    /// [`Widget`]: crate::ui::Widget
587    /// [`needs_update`]: crate::ui::Widget::needs_update
588    pub fn has_changed(&self) -> bool {
589        self.data.has_changed()
590    }
591
592    /// A function that checks if the data has been updated
593    ///
594    /// Do note that this function will check for the specific
595    /// [`RwData`] that was used in its creation, so if you call
596    /// [`read`] on that specific [`RwData`] for example, this
597    /// function will start returning `false`.
598    ///
599    /// [`read`]: RwData::read
600    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
601        self.data.checker()
602    }
603}
604
605// SAFETY: The only parts that are accessible from other threads are
606// the atomic counters from the Arcs. Everything else can only be
607// acquired when there is a Pass, i.e., on the main thread.
608unsafe impl<I: ?Sized + 'static, O: 'static> Send for DataMap<I, O> {}
609unsafe impl<I: ?Sized + 'static, O: 'static> Sync for DataMap<I, O> {}
610
611/// A mutable mapping of an [`RwData`]
612///
613/// This works very similarly to the [`DataMap`], except the function
614/// is allowed to mutate the data, so it takes a `&mut Pass` instead
615/// of a regular `&Pass`.
616pub struct MutDataMap<I: ?Sized + 'static, O: 'static> {
617    data: RwData<I>,
618    map: Arc<RefCell<dyn FnMut(&mut I) -> O>>,
619}
620
621impl<I: ?Sized, O> MutDataMap<I, O> {
622    /// Call this `DataMap`'s mapping function, returning the output
623    pub fn call(&self, pa: &mut Pass) -> O {
624        self.map.borrow_mut()(self.data.write(pa))
625    }
626
627    /// Maps the value within, works just like [`RwData::map`]
628    pub fn map<O2>(self, mut f: impl FnMut(O) -> O2 + 'static) -> MutDataMap<I, O2> {
629        self.data
630            .map_mut(move |input| f(self.map.borrow_mut()(input)))
631    }
632
633    /// Wether someone else called [`write`] or [`write_as`] since the
634    /// last [`read`] or [`write`]
635    ///
636    /// Do note that this *DOES NOT* mean that the value inside has
637    /// actually been changed, it just means a mutable reference was
638    /// acquired after the last call to [`has_changed`].
639    ///
640    /// Some types like [`Text`], and traits like [`Widget`] offer
641    /// [`needs_update`] methods, you should try to determine what
642    /// parts to look for changes.
643    ///
644    /// Generally though, you can use this method to gauge that.
645    ///
646    /// [`write`]: RwData::write
647    /// [`write_as`]: RwData::write_as
648    /// [`read`]: RwData::read
649    /// [`has_changed`]: RwData::has_changed
650    /// [`Text`]: crate::text::Text
651    /// [`Widget`]: crate::ui::Widget
652    /// [`needs_update`]: crate::ui::Widget::needs_update
653    pub fn has_changed(&self) -> bool {
654        self.data.has_changed()
655    }
656
657    /// A function that checks if the data has been updated
658    ///
659    /// Do note that this function will check for the specific
660    /// [`RwData`] that was used in its creation, so if you call
661    /// [`read`] on that specific [`RwData`] for example, this
662    /// function will start returning `false`.
663    ///
664    /// [`read`]: RwData::read
665    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
666        self.data.checker()
667    }
668}
669
670// SAFETY: The only parts that are accessible from other threads are
671// the atomic counters from the Arcs. Everything else can only be
672// acquired when there is a Pass, i.e., on the main thread.
673unsafe impl<I: ?Sized + 'static, O: 'static> Send for MutDataMap<I, O> {}
674unsafe impl<I: ?Sized + 'static, O: 'static> Sync for MutDataMap<I, O> {}
675
676/// A struct used for asynchronously mutating [`RwData`]s without a
677/// [`Pass`]
678///
679/// This works by wrapping the `RwData` and collecting every mutating
680/// function inside a separate [`Mutex`]. Whenever you access the
681/// `Data`, the changes are applied to it.
682///
683/// With this in mind, one limitation of this type is that every
684/// access must make use of a `&mut Pass`, with the exception of
685/// [`BulkDataWriter::try_read`], which returns `Some` only when there
686/// have been no changes to the `Data`.
687#[derive(Default)]
688pub struct BulkDataWriter<Data: Default + 'static> {
689    actions: LazyLock<Arc<Mutex<Vec<Box<dyn FnOnce(&mut Data) + Send + 'static>>>>>,
690    data: LazyLock<RwData<Data>>,
691}
692
693impl<Data: Default + 'static> BulkDataWriter<Data> {
694    /// Returns a new `BulkDataWriter`
695    ///
696    /// Considering the fact that this struct is almost exclusively
697    /// used in `static` variables, I have decided to make its
698    /// constructor `const`, to facilitate its usage.
699    #[allow(clippy::new_without_default)]
700    pub const fn new() -> Self {
701        Self {
702            actions: LazyLock::new(|| Arc::new(Mutex::new(Vec::new()))),
703            data: LazyLock::new(|| RwData::new(Data::default())),
704        }
705    }
706
707    /// Adds a mutating function to the list of functions to call upon
708    /// accessing the `Data`
709    ///
710    /// This is useful for allowing mutation from any thread, and
711    /// without needing [`Pass`]es. `duat-core` makes extensive use of
712    /// this function in order to provide pleasant to use APIs.
713    pub fn mutate(&self, f: impl FnOnce(&mut Data) + Send + 'static) {
714        self.actions.lock().unwrap().push(Box::new(f));
715    }
716
717    /// Accesses the `Data`, calling all added actions
718    ///
719    /// This function will call all actions that were sent by the
720    /// [`BulkDataWriter::mutate`] function in order to write to the
721    /// `Data` asynchronously.
722    pub fn write<'p>(&'p self, pa: &'p mut Pass) -> &'p mut Data {
723        let data = self.data.write(pa);
724        for action in self.actions.lock().unwrap().drain(..) {
725            action(data);
726        }
727        data
728    }
729
730    /// Attempts to read the `Data`
731    ///
732    /// This function will return [`None`] if there are pending
733    /// actions that need to happen before reading/writing. You should
734    /// almost always prefer calling [`BulkDataWriter::write`]
735    /// instead.
736    pub fn try_read<'p>(&'p self, pa: &'p Pass) -> Option<&'p Data> {
737        self.actions
738            .lock()
739            .unwrap()
740            .is_empty()
741            .then(|| self.data.read(pa))
742    }
743
744    /// Maps the value to another value with a mutating function
745    ///
746    /// This will apply the delayed updting of
747    /// [`BulkDataWriter::write`] every time the mapping is called, so
748    /// the value always stays up to date.
749    pub fn map_mut<Ret: 'static>(
750        &self,
751        mut map: impl FnMut(&mut Data) -> Ret + 'static,
752    ) -> MutDataMap<Data, Ret> {
753        let actions = self.actions.clone();
754        self.data.map_mut(move |data| {
755            for action in actions.lock().unwrap().drain(..) {
756                action(data);
757            }
758            map(data)
759        })
760    }
761}
762
763/// A checking struct that periodically returns `true`
764pub struct PeriodicChecker(Arc<AtomicBool>);
765
766impl PeriodicChecker {
767    /// Returns a new [`PeriodicChecker`]
768    pub fn new(duration: Duration) -> Self {
769        let has_elapsed = Arc::new(AtomicBool::new(false));
770        std::thread::spawn({
771            let has_elapsed = has_elapsed.clone();
772            move || {
773                while !crate::context::will_reload_or_quit() {
774                    std::thread::sleep(duration);
775                    has_elapsed.store(true, Ordering::Relaxed);
776                }
777            }
778        });
779
780        Self(has_elapsed)
781    }
782
783    /// Checks if the requested [`Duration`] has elapsed
784    pub fn check(&self) -> bool {
785        self.0.fetch_and(false, Ordering::Relaxed)
786    }
787}
788
789impl Default for PeriodicChecker {
790    fn default() -> Self {
791        Self::new(Duration::from_secs(1))
792    }
793}
794
795/// A key for reading/writing to [`RwData`]
796///
797/// This key is necessary in order to prevent breakage of the number
798/// one rule of Rust: any number of shared references, or one
799/// exclusive reference.
800///
801/// When you call [`RwData::read`], any call to [`RwData::write`] may
802/// end up breaking this rule, and vice-versa, which is why this
803/// struct is necessary.
804///
805/// One downside of this approach is that it is even more restrictive
806/// than Rust's rule of thumb, since that one is enforced on
807/// individual instances, while this one is enforced on all
808/// [`RwData`]s. This (as far as i know) cannot be circumvented, as a
809/// more advanced compile time checker (that distinguishes
810/// [`RwData<T>`]s of different `T`s, for example) does not seem
811/// feasible without the use of unfinished features, which I am not
812/// willing to use.
813pub struct Pass(PhantomData<()>);
814
815impl Pass {
816    /// Returns a new instance of [`Pass`]
817    ///
818    /// Be careful when using this!
819    pub(crate) const unsafe fn new() -> Self {
820        Pass(PhantomData)
821    }
822
823    /// Writes to many [`RwData`]-like structs at once
824    ///
825    /// This function accepts tuples (or a single element) of
826    /// references to types that implement the [`WriteableData`]
827    /// trait, which is one of the following:
828    ///
829    /// - [`RwData`]: Duat's regular smart pointer.
830    /// - [`BulkDataWriter`]: A pointer to lazyly updated data.
831    /// - [`Handle`]: A handle for a [`Widget`]
832    /// - [`RwArea`]: A handle for a `Widget`'s [`Area`]
833    ///
834    /// Here's an example, which writes to two `RwData`s at the same
835    /// time as a `Handle`:
836    ///
837    /// ```rust
838    /// # duat_core::doc_duat!(duat);
839    /// use duat::{data::RwData, prelude::*};
840    /// setup_duat!(setup);
841    ///
842    /// fn setup() {
843    ///     let (num1, num2) = (RwData::new(0), RwData::new(0));
844    ///     hook::add::<BufferOpened>(move |pa, handle: &Handle| {
845    ///         let (num1, num2, buf) = pa.write_many((&num1, &num2, handle));
846    ///         // Rest of the function writes to all of them at the same time.
847    ///     });
848    /// }
849    /// ```
850    ///
851    /// This allows for much more flexibility when writing to global
852    /// state, which should hopefully lead to more streamlined
853    /// functions
854    ///
855    /// # Panics
856    ///
857    /// This function will panic if any of the elements of the tuple
858    /// point to the same data as any other element, for example, with
859    /// the earlier code snippet:
860    ///
861    /// ```rust
862    /// # duat_core::doc_duat!(duat);
863    /// use duat::{data::RwData, prelude::*};
864    /// setup_duat!(setup);
865    ///
866    /// fn setup() {
867    ///     let num1 = RwData::new(0);
868    ///     // num2 is now a clone of num1
869    ///     let num2 = num1.clone();
870    ///     hook::add::<BufferOpened>(move |pa, handle: &Handle| {
871    ///         let (num1, num2, buf) = pa.write_many((&num1, &num2, handle));
872    ///         // Rest of the function writes to all of them at the same time.
873    ///     });
874    /// }
875    /// ```
876    ///
877    /// Since `num1` and `num2` point to the same data, you'd be
878    /// getting two `&mut i32` for the same variable, which violates
879    /// rust's "mutability xor aliasing" rule. This is why this will
880    /// panic. If you want a non-panicking version of this function,
881    /// check out [`Pass::try_write_many`], which returns a [`Result`]
882    /// instead.
883    ///
884    /// [`Handle`]: crate::context::Handle
885    /// [`RwArea`]: crate::ui::RwArea
886    /// [`Area`]: crate::ui::Area
887    #[track_caller]
888    pub fn write_many<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
889        &'p mut self,
890        tup: Tup,
891    ) -> Tup::Return {
892        if let Some(ret) = tup.write_all(self) {
893            ret
894        } else {
895            panic!("Tried writing to the same data multiple times");
896        }
897    }
898
899    /// Tries writing to many [`RwData`]-like structs at once
900    ///
901    /// This function accepts tuples (or a single element) of
902    /// references to types that implement the [`WriteableData`]
903    /// trait, which is one of the following:
904    ///
905    /// - [`RwData`]: Duat's regular smart pointer.
906    /// - [`BulkDataWriter`]: A pointer to lazyly updated data.
907    /// - [`Handle`]: A handle for a [`Widget`]
908    /// - [`RwArea`]: A handle for a `Widget`'s [`Area`]
909    ///
910    /// This function works exactly like [`Pass::write_many`],
911    /// however, instead of panicking, this function returns a
912    /// [`Result`], returning an [`Err`] if any of the tuple's
913    /// elements point to the same data as any of the other elements.
914    ///
915    /// [`Handle`]: crate::context::Handle
916    /// [`RwArea`]: crate::ui::RwArea
917    /// [`Area`]: crate::ui::Area
918    pub fn try_write_many<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
919        &'p mut self,
920        tup: Tup,
921    ) -> Result<Tup::Return, crate::text::Text> {
922        tup.write_all(self)
923            .ok_or_else(|| crate::text::txt!("Tried writing to the same data multiple times"))
924    }
925}
926
927/// A tuple of [`WriteableData`], used for writing to many things at
928/// once
929#[doc(hidden)]
930pub trait WriteableTuple<'p, _Dummy> {
931    type Return;
932
933    #[doc(hidden)]
934    fn write_all(self, pa: &'p mut Pass) -> Option<Self::Return>;
935
936    #[doc(hidden)]
937    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>>;
938}
939
940macro_rules! implWriteableTuple {
941    ($(($tup:ident, $dummy:ident)),+) => {
942        #[allow(non_snake_case)]
943        impl<'p, $($tup),+, $($dummy),+> WriteableTuple<'p, ($(&mut $dummy),+)> for ($($tup),+)
944        where
945            $($tup: WriteableTuple<'p, $dummy>),+
946        {
947            type Return = ($($tup::Return),+);
948
949            fn write_all(self, _: &'p mut Pass) -> Option<Self::Return> {
950                if self.state_ptrs().into_iter().enumerate().any(|(lhs, i)| {
951                    self.state_ptrs()
952                        .into_iter()
953                        .enumerate()
954                        .any(|(rhs, j)| lhs == rhs && i != j)
955                }) {
956                    return None;
957                }
958
959                let ($($tup),+) = self;
960
961				/// SAFETY: The ptrs are already verifiably not pointing to the same data.
962                static PASS: Pass = unsafe { Pass::new() };
963
964                Some(($(
965                    $tup.write_all(
966                        unsafe { (&raw const PASS as *mut Pass).as_mut() }.unwrap()
967                    )
968                    .unwrap()
969                ),+))
970            }
971
972            fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
973                let ($($tup),+) = self;
974
975                implWriteableTuple!(@chain $($tup),+)
976            }
977        }
978    };
979
980    (@chain $tup:ident $(, $rest:ident)*) => {
981        $tup.state_ptrs().into_iter().chain(implWriteableTuple!(@chain $($rest),*))
982    };
983    (@chain ) => { [] };
984}
985
986impl<'p, Data, T> WriteableTuple<'p, (&mut T,)> for &'p Data
987where
988    Data: WriteableData<'p, T>,
989    T: ?Sized + 'p,
990{
991    type Return = &'p mut T;
992
993    fn write_all(self, pa: &'p mut Pass) -> Option<Self::Return> {
994        Some(self.write_one_of_many(pa))
995    }
996
997    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
998        [self.cur_state_ptr()]
999    }
1000}
1001
1002implWriteableTuple!((D0, T0), (D1, T1));
1003implWriteableTuple!((D0, T0), (D1, T1), (D2, T2));
1004implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3));
1005implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4));
1006implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5));
1007#[rustfmt::skip]
1008implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6));
1009#[rustfmt::skip]
1010implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7));
1011#[rustfmt::skip]
1012implWriteableTuple!(
1013    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8)
1014);
1015#[rustfmt::skip]
1016implWriteableTuple!(
1017    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
1018    (D9, T9)
1019);
1020#[rustfmt::skip]
1021implWriteableTuple!(
1022    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
1023    (D9, T9), (D10, T10)
1024);
1025#[rustfmt::skip]
1026implWriteableTuple!(
1027    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
1028    (D9, T9), (D10, T10), (D11, T11)
1029);
1030
1031impl<'p, const N: usize, Tup, Dummy> WriteableTuple<'p, [Dummy; N]> for [Tup; N]
1032where
1033    Tup: WriteableTuple<'p, Dummy> + 'p,
1034{
1035    type Return = [Tup::Return; N];
1036
1037    fn write_all(self, _: &'p mut Pass) -> Option<Self::Return> {
1038        if self.state_ptrs().into_iter().enumerate().any(|(lhs, i)| {
1039            self.state_ptrs()
1040                .into_iter()
1041                .enumerate()
1042                .any(|(rhs, j)| lhs == rhs && i != j)
1043        }) {
1044            return None;
1045        }
1046
1047        static PASS: Pass = unsafe { Pass::new() };
1048
1049        Some(self.map(|tup| {
1050            let pa = &raw const PASS as *mut Pass;
1051            tup.write_all(unsafe { pa.as_mut() }.unwrap()).unwrap()
1052        }))
1053    }
1054
1055    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
1056        self.iter().flat_map(|tup| tup.state_ptrs())
1057    }
1058}
1059
1060/// A trait for writing to multiple [`RwData`]-like structs at once
1061#[doc(hidden)]
1062pub trait WriteableData<'p, T: ?Sized + 'p>: InnerWriteableData {
1063    /// Just like [`RwData::write`]
1064    #[doc(hidden)]
1065    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T;
1066
1067    /// A pointer for [`Pass::try_write_many`]
1068    #[doc(hidden)]
1069    fn cur_state_ptr(&self) -> CurStatePtr<'_>;
1070}
1071
1072impl<'p, T: ?Sized + 'p> WriteableData<'p, T> for RwData<T> {
1073    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T {
1074        self.write(pa)
1075    }
1076
1077    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1078        CurStatePtr(&self.cur_state)
1079    }
1080}
1081
1082impl<'p, T: Default> WriteableData<'p, T> for BulkDataWriter<T> {
1083    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T {
1084        self.write(pa)
1085    }
1086
1087    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1088        CurStatePtr(&self.data.cur_state)
1089    }
1090}
1091
1092impl<'p, W: Widget> WriteableData<'p, W> for crate::context::Handle<W> {
1093    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut W {
1094        self.write(pa)
1095    }
1096
1097    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1098        CurStatePtr(&self.widget().cur_state)
1099    }
1100}
1101
1102impl<'p> WriteableData<'p, crate::ui::Area> for crate::ui::RwArea {
1103    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut crate::ui::Area {
1104        self.write(pa)
1105    }
1106
1107    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1108        CurStatePtr(&self.0.cur_state)
1109    }
1110}
1111
1112/// To prevent outside implementations
1113trait InnerWriteableData {}
1114impl<T: ?Sized> InnerWriteableData for RwData<T> {}
1115impl<T: Default> InnerWriteableData for BulkDataWriter<T> {}
1116impl<W: Widget> InnerWriteableData for crate::context::Handle<W> {}
1117impl InnerWriteableData for crate::ui::RwArea {}
1118
1119/// A struct for comparison when calling [`Pass::write_many`]
1120#[doc(hidden)]
1121#[derive(Clone, Copy)]
1122pub struct CurStatePtr<'p>(&'p Arc<AtomicUsize>);
1123
1124impl std::cmp::PartialEq for CurStatePtr<'_> {
1125    fn eq(&self, other: &Self) -> bool {
1126        Arc::ptr_eq(self.0, other.0)
1127    }
1128}