maycoon_core/app/
update.rs

1use bitflags::bitflags;
2use std::sync::Arc;
3use std::sync::atomic::{AtomicU8, Ordering};
4
5bitflags! {
6    /// Update bitflags to define which part of the App should Update.
7    ///
8    /// Possible values:
9    /// - **EVAL** - Re-evaluate the widget tree.
10    /// - **DRAW** - Re-draw the widget tree.
11    /// - **LAYOUT** - Re-layout the widget tree.
12    /// - **FORCE** - Force the App to re-evaluate, re-draw and re-layout the widget tree.
13    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14    pub struct Update: u8 {
15        /// Re-evaluate the widget tree.
16        const EVAL   = 0b00000001;
17        /// Re-draw the widget tree.
18        const DRAW   = 0b00000010;
19        /// Re-layout the widget tree.
20        const LAYOUT = 0b00000100;
21        /// Force the App to re-evaluate, re-draw and re-layout the widget tree.
22        const FORCE  = 0b00001000;
23        /// Makes the App exit.
24        const EXIT   = 0b00010000;
25    }
26}
27
28/// Manages updates for the application lifecycle.
29///
30/// It's using atomic operations to ensure lockless thread-safety.
31#[derive(Clone, Debug)]
32pub struct UpdateManager {
33    update: Arc<AtomicU8>,
34}
35
36impl UpdateManager {
37    /// Creates a new `UpdateManager`.
38    #[inline(always)]
39    pub fn new() -> Self {
40        Self {
41            update: Arc::new(AtomicU8::new(Update::FORCE.bits())),
42        }
43    }
44
45    /// Inserts the given `Update` into the `UpdateManager` using bitwise OR.
46    #[inline(always)]
47    pub fn insert(&self, update: Update) {
48        tracing::debug!("inserting update {update:?}");
49        self.update.fetch_or(update.bits(), Ordering::AcqRel);
50    }
51
52    /// Removes the given `Update` from the `UpdateManager` using bitwise AND.
53    #[inline(always)]
54    pub fn remove(&self, update: Update) {
55        tracing::debug!("removing update {update:?}");
56        self.update.fetch_and(!update.bits(), Ordering::AcqRel);
57    }
58
59    /// Returns the current `Update` of the `UpdateManager`.
60    #[inline(always)]
61    pub fn get(&self) -> Update {
62        Update::from_bits(self.update.load(Ordering::Acquire))
63            .expect("failed to decode update bits")
64    }
65
66    /// Sets the current `Update` of the `UpdateManager`.
67    #[inline(always)]
68    pub fn set(&self, update: Update) {
69        tracing::debug!("setting update {update:?}");
70        self.update.store(update.bits(), Ordering::Release);
71    }
72
73    /// Clears the current `Update` flags of the `UpdateManager`.
74    #[inline(always)]
75    pub fn clear(&self) {
76        self.update.store(0, Ordering::Release);
77    }
78}
79
80impl Default for UpdateManager {
81    #[inline(always)]
82    fn default() -> Self {
83        Self::new()
84    }
85}