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}