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}