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//! [`Arc<Mutex>`]: std::sync::Arc
45//! [`Arc<RwLock>`]: std::sync::Arc
46//! [`read`]: RwData::read
47//! [`write`]: RwData::write
48use std::{
49    self,
50    any::TypeId,
51    cell::{RefCell, UnsafeCell},
52    marker::PhantomData,
53    sync::{
54        Arc,
55        atomic::{AtomicBool, AtomicUsize, Ordering},
56    },
57    time::Duration,
58};
59
60use crate::ui::Widget;
61
62/// A container for shared read/write state
63///
64/// This is the struct used internally (and externally) to allow for
65/// massively shareable state in duat's API. Its main purpose is to
66/// hold all of the [`Widget`]s in Duat, making them available for
67/// usage from any function with access to a [`Pass`].
68///
69/// # [`Pass`]es
70///
71/// The [`Pass`] is a sort of "key" for accessing the value within an
72/// [`RwData`], it's purpose is to maintain Rust's number one rule,
73/// i.e. one exclusive reference or multiple shared references, and
74/// that is done by borrowing the [`Pass`] mutably or non mutably.
75/// That comes with some limitations, of course, mainly that you can't
76/// really mutate two [`RwData`]s at the same time, even if it is
77/// known that they don't point to the same data.
78///
79/// There are some common exceptions to this, where Duat provides some
80/// safe way to do that when it is known that the two types are not
81/// the same.
82///
83/// # Not [`Send`]/[`Sync`]
84///
85/// Internally, the [`RwData`] makes use of an [`Arc<RefCell>`]. The
86/// usage of an [`Arc<RefCell>`] over an [`Arc<Mutex>`] is, i've
87/// assumed, a necessary evil in order to preserve the aforementioned
88/// rule. But the lack of [`Send`]/[`Sync`] does confer the [`RwData`]
89/// some advantages:
90///
91/// * Deadlocks are impossible, being replaced by much easier to debug
92///   panics.
93/// * The order in which data is accessed doesn't matter, unlike with
94///   [`Mutex`]es.
95/// * Performance of unlocking and cloning should generally be better,
96///   since no atomic operations are done (I actually managed to
97///   observe this, where in my rudimentary benchmarks against neovim,
98///   the [`Arc<Mutex>`] version was very frequently losing to a
99///   comparable neovim build.
100///
101/// However, I admit that there are also some drawbacks, the most
102/// notable being the difficulty of reading or writing to [`Text`]
103/// from outside of the main thread. But for the most common usecase
104/// where that will be needed ([`Parser`]s), a [`Send`]/[`Sync`]
105/// solution will be provided soon.
106///
107/// [`Arc<Mutex>`]: std::sync::Arc
108/// [`Mutex`]: std::sync::Mutex
109/// [`Parser`]: crate::buffer::Parser
110/// [`Text`]: crate::text::Text
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<'a>(&'a self, _: &'a Pass) -> &'a 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<'a, U: 'static>(&'a self, _: &'a Pass) -> Option<&'a 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<'a>(&'a self, _: &'a mut Pass) -> &'a 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<'a, U: 'static>(&'a self, _: &'a mut Pass) -> Option<&'a 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    /// Simulates a [`write`] without actually writing
277    ///
278    /// This is useful if you want to tell Duat that you want
279    /// [`has_changed`] to return `true`, but you don't have a
280    /// [`Pass`] available to [`write`] the value with.
281    ///
282    /// [`write`]: Self::write
283    /// [`has_changed`]: Self::has_changed
284    pub fn declare_written(&self) {
285        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
286        self.read_state.store(prev + 1, Ordering::Relaxed);
287    }
288
289    ////////// Mapping of the inner value
290
291    /// Maps the value to another value with a function
292    ///
293    /// This function will return a struct that acts like a "read
294    /// only" version of [`RwData`], which also maps the value to
295    /// a return type.
296    pub fn map<Ret: 'static>(&self, map: impl FnMut(&T) -> Ret + 'static) -> DataMap<T, Ret> {
297        let RwData { value, cur_state, .. } = self.clone();
298        let data = RwData {
299            value,
300            cur_state,
301            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed))),
302            ty: TypeId::of::<T>(),
303        };
304
305        DataMap { data, map: Arc::new(RefCell::new(map)) }
306    }
307
308    /// Attempts to downcast an [`RwData`] to a concrete type
309    ///
310    /// Returns [`Some(RwData<U>)`] if the value within is of type
311    /// `U`. For unsized types, `U` is the type parameter
312    /// passed when calling [`RwData::new_unsized`].
313    ///
314    /// [`Some(RwData<U>)`]: Some
315    pub fn try_downcast<U: 'static>(&self) -> Option<RwData<U>> {
316        if TypeId::of::<U>() != self.ty {
317            return None;
318        }
319
320        let ptr = Arc::into_raw(self.value.clone());
321        // SAFETY: TypeId argument "guarantees" this
322        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<U>) };
323        Some(RwData {
324            value,
325            cur_state: self.cur_state.clone(),
326            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
327            ty: TypeId::of::<U>(),
328        })
329    }
330
331    ////////// Querying functions
332
333    /// Wether this [`RwData`] and another point to the same value
334    pub fn ptr_eq<U: ?Sized>(&self, other: &RwData<U>) -> bool {
335        Arc::as_ptr(&self.value).addr() == Arc::as_ptr(&other.value).addr()
336    }
337
338    /// The [`TypeId`] of the concrete type within
339    pub fn type_id(&self) -> TypeId {
340        self.ty
341    }
342
343    /// Wether the concrete [`TypeId`] matches that of `U`
344    pub fn is<U: 'static>(&self) -> bool {
345        self.ty == TypeId::of::<U>()
346    }
347
348    /// Wether someone else called [`write`] or [`write_as`] since the
349    /// last [`read`] or `write`
350    ///
351    /// Do note that this *DOES NOT* mean that the value inside has
352    /// actually been changed, it just means a mutable reference was
353    /// acquired after the last call to [`has_changed`].
354    ///
355    /// Some types like [`Text`], and traits like [`Widget`] offer
356    /// [`has_changed`](crate::ui::Widget::needs_update) methods,
357    /// you should try to determine what parts to look for changes.
358    ///
359    /// Generally though, you can use this method to gauge that.
360    ///
361    /// [`write`]: Self::write
362    /// [`write_as`]: Self::write_as
363    /// [`read`]: Self::read
364    /// [`has_changed`]: Self::has_changed
365    /// [`Text`]: crate::text::Text
366    /// [`Widget`]: crate::ui::Widget
367    pub fn has_changed(&self) -> bool {
368        self.read_state.load(Ordering::Relaxed) < self.cur_state.load(Ordering::Relaxed)
369    }
370
371    /// A function that checks if the data has been updated
372    ///
373    /// Do note that this function will check for the specific
374    /// [`RwData`] that was used in its creation, so if you call
375    /// [`read`] on that specific [`RwData`] for example, this
376    /// function will start returning `false`.
377    ///
378    /// [`read`]: Self::read
379    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
380        let (read, cur) = (self.read_state.clone(), self.cur_state.clone());
381        move || read.load(Ordering::Relaxed) < cur.load(Ordering::Relaxed)
382    }
383}
384
385impl<W: Widget> RwData<W> {
386    /// Downcasts [`RwData<impl Widget>`] to [`RwData<dyn Widget>`]
387    pub fn to_dyn_widget(&self) -> RwData<dyn Widget> {
388        let ptr = Arc::into_raw(self.value.clone());
389        // SAFETY: Implements Widget
390        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<dyn Widget>) };
391        RwData {
392            value,
393            cur_state: self.cur_state.clone(),
394            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
395            ty: self.ty,
396        }
397    }
398}
399
400// SAFETY: The only parts that are accessible from other threads are
401// the atomic counters from the Arcs. Everything else can only be
402// acquired when there is a Pass, i.e., on the main thread.
403unsafe impl<T: ?Sized + 'static> Send for RwData<T> {}
404unsafe impl<T: ?Sized + 'static> Sync for RwData<T> {}
405
406impl<T: ?Sized + 'static> RwData<T> {}
407
408impl<T: ?Sized> Clone for RwData<T> {
409    fn clone(&self) -> Self {
410        Self {
411            value: self.value.clone(),
412            ty: self.ty,
413            cur_state: self.cur_state.clone(),
414            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
415        }
416    }
417}
418
419impl<T: Default + 'static> Default for RwData<T> {
420    fn default() -> Self {
421        Self {
422            value: Arc::default(),
423            cur_state: Arc::new(AtomicUsize::new(1)),
424            read_state: Arc::new(AtomicUsize::new(0)),
425            ty: TypeId::of::<T>(),
426        }
427    }
428}
429
430/// A mapping of an [`RwData`]
431pub struct DataMap<I: ?Sized + 'static, O: 'static> {
432    data: RwData<I>,
433    map: Arc<RefCell<dyn FnMut(&I) -> O>>,
434}
435
436impl<I: ?Sized, O> DataMap<I, O> {
437    /// Call this `DataMap`'s mapping function, returning the output
438    pub fn call(&self, pa: &Pass) -> O {
439        self.map.borrow_mut()(self.data.read(pa))
440    }
441
442    /// Maps the value within, works just like [`RwData::map`]
443    pub fn map<O2>(self, mut f: impl FnMut(O) -> O2 + 'static) -> DataMap<I, O2> {
444        self.data.map(move |input| f(self.map.borrow_mut()(input)))
445    }
446
447    /// Wether someone else called [`write`] or [`write_as`] since the
448    /// last [`read`] or [`write`]
449    ///
450    /// Do note that this *DOES NOT* mean that the value inside has
451    /// actually been changed, it just means a mutable reference was
452    /// acquired after the last call to [`has_changed`].
453    ///
454    /// Some types like [`Text`], and traits like [`Widget`] offer
455    /// [`needs_update`] methods, you should try to determine what
456    /// parts to look for changes.
457    ///
458    /// Generally though, you can use this method to gauge that.
459    ///
460    /// [`write`]: RwData::write
461    /// [`write_as`]: RwData::write_as
462    /// [`read`]: RwData::read
463    /// [`has_changed`]: RwData::has_changed
464    /// [`Text`]: crate::text::Text
465    /// [`Widget`]: crate::ui::Widget
466    /// [`needs_update`]: crate::ui::Widget::needs_update
467    pub fn has_changed(&self) -> bool {
468        self.data.has_changed()
469    }
470
471    /// A function that checks if the data has been updated
472    ///
473    /// Do note that this function will check for the specific
474    /// [`RwData`] that was used in its creation, so if you call
475    /// [`read`] on that specific [`RwData`] for example, this
476    /// function will start returning `false`.
477    ///
478    /// [`read`]: RwData::read
479    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
480        self.data.checker()
481    }
482}
483
484// SAFETY: The only parts that are accessible from other threads are
485// the atomic counters from the Arcs. Everything else can only be
486// acquired when there is a Pass, i.e., on the main thread.
487unsafe impl<I: ?Sized + 'static, O: 'static> Send for DataMap<I, O> {}
488unsafe impl<I: ?Sized + 'static, O: 'static> Sync for DataMap<I, O> {}
489
490/// A key for reading/writing to [`RwData`]
491///
492/// This key is necessary in order to prevent breakage of the number
493/// one rule of Rust: any number of shared references, or one
494/// exclusive reference.
495///
496/// When you call [`RwData::read`], any call to [`RwData::write`] may
497/// end up breaking this rule, and vice-versa, which is why this
498/// struct is necessary.
499///
500/// One downside of this approach is that it is even more restrictive
501/// than Rust's rule of thumb, since that one is enforced on
502/// individual instances, while this one is enforced on all
503/// [`RwData`]s. This (as far as i know) cannot be circumvented, as a
504/// more advanced compile time checker (that distinguishes
505/// [`RwData<T>`]s of different `T`s, for example) does not seem
506/// feasible without the use of unfinished features, which I am not
507/// willing to use.
508pub struct Pass(PhantomData<()>);
509
510impl Pass {
511    /// Returns a new instance of [`Pass`]
512    ///
513    /// Be careful when using this!
514    pub(crate) const unsafe fn new() -> Self {
515        Pass(PhantomData)
516    }
517
518    /// Writes to two [`RwData`] at the same time
519    ///
520    /// This can only be done when the `RwData`s are of different
521    /// types since, if they were of the same type, they could be
522    /// pointing to the same data, which would be undefined behaviour.
523    ///
524    /// Also, this may only be done with sized types, since for
525    /// example, an [`RwData<Buffer>`] could point to the same
526    /// [`Buffer`] as some [`RwData<dyn Widget>`], even if `dyn
527    /// Widget` and `Buffer` are "different types.
528    ///
529    /// # Panics
530    ///
531    /// For now, due to the inability to compary two [`TypeId`]s at
532    /// compile time in stable Rust, calling this function on two
533    /// [`RwData`]s of the same type will simply panic at runtime.
534    ///
535    /// However, in the future, once [`PartialEq`] is allowed in const
536    /// contexts, this function will refuse to compile if the
537    /// `RwData`s are of the same type.
538    ///
539    /// In practice, the outcome ends up being the same, since
540    /// breaking that invariant results in the rejection of your conde
541    /// regardless, it will just happen in a more convenient place in
542    /// the future.
543    ///
544    /// [`Buffer`]: crate::buffer::Buffer
545    pub fn write_two<'a, L: 'static, R: 'static>(
546        &'a mut self,
547        lhs: &'a RwData<L>,
548        rhs: &'a RwData<R>,
549    ) -> (&'a mut L, &'a mut R) {
550        static mut INTERNAL_PASS: Pass = unsafe { Pass::new() };
551
552        assert!(
553            TypeId::of::<L>() != TypeId::of::<R>(),
554            "Can't write to two RwData of the same type, since they may point to the same data"
555        );
556
557        #[allow(static_mut_refs)]
558        (lhs.write(self), rhs.write(unsafe { &mut INTERNAL_PASS }))
559    }
560
561    /// Writes to one [`RwData`] and reads from another at the same
562    /// time
563    ///
564    /// This can only be done when the `RwData`s are of different
565    /// types since, if they were of the same type, they could be
566    /// pointing to the same data, which would be undefined behaviour.
567    ///
568    /// Also, this may only be done with sized types, since for
569    /// example, an [`RwData<Buffer>`] could point to the same
570    /// [`Buffer`] as some [`RwData<dyn Widget>`], even if `dyn
571    /// Widget` and `Buffer` are "different types.
572    ///
573    /// # Panics
574    ///
575    /// For now, due to the inability to compary two [`TypeId`]s at
576    /// compile time in stable Rust, calling this function on two
577    /// [`RwData`]s of the same type will simply panic at runtime.
578    ///
579    /// However, in the future, once [`PartialEq`] is allowed in const
580    /// contexts, this function will refuse to compile if the
581    /// `RwData`s are of the same type.
582    ///
583    /// In practice, the outcome ends up being the same, since
584    /// breaking that invariant results in the rejection of your conde
585    /// regardless, it will just happen in a more convenient place in
586    /// the future.
587    ///
588    /// [`Buffer`]: crate::buffer::Buffer
589    pub fn read_and_write<'a, L: 'static, R: 'static>(
590        &'a mut self,
591        lhs: &'a RwData<L>,
592        rhs: &'a RwData<R>,
593    ) -> (&'a L, &'a mut R) {
594        static INTERNAL_PASS: &Pass = &unsafe { Pass::new() };
595
596        assert!(
597            TypeId::of::<L>() != TypeId::of::<R>(),
598            "Can't read and write to RwDatas of the same type, since they may point to the same \
599             data"
600        );
601
602        (lhs.read(INTERNAL_PASS), rhs.write(self))
603    }
604
605    /// Tries to write to two [`RwData`] at the same time, failing if
606    /// they point to the same data
607    ///
608    /// Almost all the time, you will want to use [`Pass::write_two`]
609    /// instead of this function, since it always returns and is
610    /// checked at compile time. There are only two situations
611    /// where you should consider using this function:
612    ///
613    /// - One or two of the [`RwData`]s point to unsized types.
614    /// - They point to the same type.
615    ///
616    /// Given these two constraints however, you should still make
617    /// sure that the two [`RwData`]s don't point to the same data.
618    ///
619    /// [`Buffer`]: crate::buffer::Buffer
620    pub fn try_write_two<'a, L: ?Sized + 'static, R: ?Sized + 'static>(
621        &'a mut self,
622        lhs: &'a RwData<L>,
623        rhs: &'a RwData<R>,
624    ) -> Option<(&'a mut L, &'a mut R)> {
625        static mut INTERNAL_PASS: Pass = unsafe { Pass::new() };
626
627        #[allow(static_mut_refs)]
628        (!lhs.ptr_eq(rhs)).then_some((lhs.write(self), rhs.write(unsafe { &mut INTERNAL_PASS })))
629    }
630
631    /// Tries to write to one [`RwData`] and reads from another at the
632    /// same time
633    ///
634    /// Almost all the time, you will want to use
635    /// [`Pass::read_and_write`] instead of this function, since
636    /// it always returns and is checked at compile time. There
637    /// are only two situations where you should consider using
638    /// this function:
639    ///
640    /// - One or two of the [`RwData`]s point to unsized types.
641    /// - They point to the same type.
642    ///
643    /// Given these two constraints however, you should still make
644    /// sure that the two [`RwData`]s don't point to the same data.
645    ///
646    /// [`Buffer`]: crate::buffer::Buffer
647    pub fn try_read_and_write<'a, L: ?Sized + 'static, R: ?Sized + 'static>(
648        &'a mut self,
649        lhs: &'a RwData<L>,
650        rhs: &'a RwData<R>,
651    ) -> Option<(&'a L, &'a mut R)> {
652        static INTERNAL_PASS: Pass = unsafe { Pass::new() };
653
654        (!lhs.ptr_eq(rhs)).then_some((lhs.read(&INTERNAL_PASS), rhs.write(self)))
655    }
656}
657
658/// A checking struct that periodically returns `true`
659pub struct PeriodicChecker(Arc<AtomicBool>);
660
661impl PeriodicChecker {
662    /// Returns a new [`PeriodicChecker`]
663    pub fn new(duration: Duration) -> Self {
664        let has_elapsed = Arc::new(AtomicBool::new(false));
665        std::thread::spawn({
666            let has_elapsed = has_elapsed.clone();
667            move || {
668                while !crate::context::will_reload_or_quit() {
669                    std::thread::sleep(duration);
670                    has_elapsed.store(true, Ordering::Relaxed);
671                }
672            }
673        });
674
675        Self(has_elapsed)
676    }
677
678    /// Checks if the requested [`Duration`] has elapsed
679    pub fn check(&self) -> bool {
680        self.0.fetch_and(false, Ordering::Relaxed)
681    }
682}
683
684impl Default for PeriodicChecker {
685    fn default() -> Self {
686        Self::new(Duration::from_secs(1))
687    }
688}