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}