Skip to main content

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;
20
21/// An RAII implementation of a “scoped read lock” of a `State`
22pub(crate) struct ReadGuard<'a> {
23    state: &'a mut State,
24    version: InstanceVersion,
25}
26
27impl<'a> ReadGuard<'a> {
28    /// Creates new `ReadGuard` with specified parameters
29    pub(crate) fn new(state: &'a mut State, version: InstanceVersion) -> Self {
30        state.rlock(version);
31        ReadGuard { version, state }
32    }
33}
34
35impl Drop for ReadGuard<'_> {
36    /// Unlocks stored `version` when `ReadGuard` goes out of scope
37    fn drop(&mut self) {
38        self.state.runlock(self.version);
39    }
40}
41
42/// `Synchronizer` result
43pub struct ReadResult<'a, T: Archive> {
44    _guard: ReadGuard<'a>,
45    entity: &'a Archived<T>,
46    switched: bool,
47}
48
49impl<'a, T: Archive> ReadResult<'a, T> {
50    /// Creates new `ReadResult` with specified parameters
51    pub(crate) fn new(guard: ReadGuard<'a>, entity: &'a Archived<T>, switched: bool) -> Self {
52        ReadResult {
53            _guard: guard,
54            entity,
55            switched,
56        }
57    }
58
59    /// Indicates whether data was switched during last read
60    pub fn is_switched(&self) -> bool {
61        self.switched
62    }
63}
64
65impl<T: Archive> Deref for ReadResult<'_, T> {
66    type Target = Archived<T>;
67
68    /// Dereferences stored `entity` for easier access
69    fn deref(&self) -> &Archived<T> {
70        self.entity
71    }
72}