mmap_sync/
guard.rs

1//! The `guard` module manages read access to shared memory, utilizing RAII (Resource Acquisition
2//! Is Initialization) principles to control access lifecycle.
3//!
4//! `ReadGuard` is the primary structure in this module. On creation, `ReadGuard` provides a
5//! reference to an entity in shared memory. This reference can be safely used until the
6//! `grace_duration` set in the `write` method of the `synchronizer` module expires.
7//!
8//! `ReadGuard` relinquishes memory access rights automatically when it goes out of scope and
9//! gets dropped, thus avoiding potential memory corruption due to lingering references.
10//! Therefore, users must ensure all `ReadGuard` instances are dropped before `grace_duration`
11//! expires.
12//!
13//! The `synchronizer` module utilizes this `guard` module to manage memory safety, allowing
14//! users to focus on their application logic.
15use rkyv::{Archive, Archived};
16use std::ops::Deref;
17
18use crate::instance::InstanceVersion;
19use crate::state::State;
20use crate::synchronizer::SynchronizerError;
21
22/// An RAII implementation of a “scoped read lock” of a `State`
23pub(crate) struct ReadGuard<'a> {
24    state: &'a mut State,
25    version: InstanceVersion,
26}
27
28impl<'a> ReadGuard<'a> {
29    /// Creates new `ReadGuard` with specified parameters
30    pub(crate) fn new(
31        state: &'a mut State,
32        version: InstanceVersion,
33    ) -> Result<Self, SynchronizerError> {
34        state.rlock(version);
35        Ok(ReadGuard { version, state })
36    }
37}
38
39impl<'a> Drop for ReadGuard<'a> {
40    /// Unlocks stored `version` when `ReadGuard` goes out of scope
41    fn drop(&mut self) {
42        self.state.runlock(self.version);
43    }
44}
45
46/// `Synchronizer` result
47pub struct ReadResult<'a, T: Archive> {
48    _guard: ReadGuard<'a>,
49    entity: &'a Archived<T>,
50    switched: bool,
51}
52
53impl<'a, T: Archive> ReadResult<'a, T> {
54    /// Creates new `ReadResult` with specified parameters
55    pub(crate) fn new(_guard: ReadGuard<'a>, entity: &'a Archived<T>, switched: bool) -> Self {
56        ReadResult {
57            _guard,
58            entity,
59            switched,
60        }
61    }
62
63    /// Indicates whether data was switched during last read
64    pub fn is_switched(&self) -> bool {
65        self.switched
66    }
67}
68
69impl<'a, T: Archive> Deref for ReadResult<'a, T> {
70    type Target = Archived<T>;
71
72    /// Dereferences stored `entity` for easier access
73    fn deref(&self) -> &Archived<T> {
74        self.entity
75    }
76}