guard.rs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use super::{ModifyAction, ModifyPublisher, PropertyPtr, Role};
  19. macro_rules! t { ($($arg:tt)*) => { trace!(target: "prop", $($arg)*); } }
  20. /// This schedules all property updates to happen at the end of the scope.
  21. /// We can therefore have fine-grained control about when property updates are
  22. /// propagated to the rest of the scenegraph.
  23. ///
  24. /// This way we avoid triggering draw updates mid draw, and changes are atomic.
  25. /// For example resizing the content view, will trigger the editbox background to
  26. /// redraw while a current window wide draw is in progress. Since the window draw
  27. /// triggered the change when we submit the draw update, it will be discarded by
  28. /// the editbox bg triggered update. However this update won't have the current
  29. /// rect and will be stale.
  30. ///
  31. /// 1. Content draw starts
  32. /// 2. Dependent property triggers and submits editbox bg redraw.
  33. /// 3. Content draw continues and now draws editbox bg with updated rect.
  34. /// 4. Finished content draw's editbox bg update is discarded in favour of #2.
  35. /// However #2 used the pre-updated rect and is now stale.
  36. ///
  37. /// We solve the above issue by batching all updates until after the draw call is finished.
  38. /// This also has the unintended side-effect of making draws much faster since they aren't
  39. /// interrupted halfway through by extra compute.
  40. pub struct PropertyAtomicGuard {
  41. updates: Vec<(PropertyPtr, Role, ModifyAction)>,
  42. }
  43. impl PropertyAtomicGuard {
  44. pub fn new() -> Self {
  45. Self { updates: vec![] }
  46. }
  47. pub(super) fn add(&mut self, prop: PropertyPtr, role: Role, action: ModifyAction) {
  48. self.updates.push((prop, role, action));
  49. }
  50. }
  51. impl Drop for PropertyAtomicGuard {
  52. fn drop(&mut self) {
  53. for (prop, role, action) in std::mem::take(&mut self.updates) {
  54. prop.on_modify.notify((role, action));
  55. }
  56. }
  57. }