Skip to main content

harmos_runtime/state/
managed.rs

1/* ***
2 *
3 * Harmos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * ***
8 */
9
10/* === Modules === */
11
12/* === Re-Exports === */
13
14/* === Imports === */
15
16// Standard Library Imports
17use std::sync::Arc;
18
19// Third Party Imports
20
21// Local Imports
22use super::{At, Error, Origin, Position, TrackedState};
23use crate::Application;
24
25/* === Constants === */
26
27/* === Macros === */
28
29/* === Type Aliases === */
30
31/* === Structs === */
32
33pub struct ManagedState<A: Application> {
34    tracked: Arc<TrackedState<A>>,
35}
36
37/* === Enums === */
38
39/* === Traits === */
40
41/* === Implementations === */
42
43impl<A: Application> ManagedState<A> {
44    pub(super) fn new(tracked: Arc<TrackedState<A>>) -> Self {
45        Self { tracked }
46    }
47
48    #[tracing::instrument(target = "harmos::state", name = "state.read", level = "debug", skip_all)]
49    pub async fn read<R>(&self, read: impl FnOnce(&A::State) -> R) -> Result<At<R>, Error> {
50        if self.tracked.poisoned() {
51            return Err(self.tracked.unavailable());
52        }
53        let state = self.tracked.state.read().await;
54        // The Writer May Have Panicked While This Reader Awaited The Lock.
55        if self.tracked.poisoned() {
56            return Err(self.tracked.unavailable());
57        }
58
59        Ok(At { value: read(&state.value), position: state.position })
60    }
61
62    #[tracing::instrument(target = "harmos::state", name = "state.at", level = "debug", skip_all)]
63    pub async fn at(&self, origin: Origin<A::State>, at: Position) -> Result<At<A::State>, Error> {
64        if self.tracked.poisoned() {
65            return Err(self.tracked.unavailable());
66        }
67
68        {
69            let tail = self.tracked.tail.read().await;
70            if tail.splits_commit(at) || tail.splits_commit(origin.position) {
71                return Err(Error::IncompleteCommit);
72            }
73        }
74        self.tracked.reads.state(origin, at).await
75    }
76}
77
78impl<A: Application> Clone for ManagedState<A> {
79    fn clone(&self) -> Self {
80        Self::new(Arc::clone(&self.tracked))
81    }
82}
83
84/* === Public Functions === */
85
86/* === Private Functions === */
87
88/* === Tests === */