1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2020-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//! RLU Traits
//!
//! The most basic abstraction for implementing types of RLU consists of two traits [`Read`] and [`Write`].
//! Either provide a function to `get()` or `get_mut` of data respectively.

use crate::{RLUVar, ReadGuard, Result, WriteGuard};

/// [`Read<T>`] provides immutable read access to the synchronized data
/// via the current managing context.
pub trait Read<T>
where
    T: Clone,
{
    /// Returns an immutable [`ReadGuard`] on the value of [`RLUVar`]
    ///
    /// This function effectively returns either the original value, if it
    /// has not been modified, or an immutable reference to the underlying
    /// write log, if the log has not been commited to memory yet. The [`ReadGuard`]
    /// ensures that after dereferencing and reading the value, all outstanding
    /// commits to the internal value will be conducted.
    ///
    /// # Example
    /// ```
    /// use stronghold_rlu::*;
    ///
    /// // create simple value, that should be managed by RLU
    /// let value = 6usize;
    ///
    /// // first we need to create a controller
    /// let ctrl = RLU::new();
    ///
    /// // via the controller  we create a RLUVar reference
    /// let rlu_var: RLUVar<usize> = ctrl.create(value);
    ///
    /// // we clone the reference to it to use it inside a thread
    /// let var_1 = rlu_var.clone();
    ///
    /// // via the controller we can spawn a thread safe context
    /// ctrl.execute(move |context| {
    ///     let inner = context.get(&var_1)?;
    ///     assert_eq!(*inner, 6);
    ///     Ok(())
    /// });
    /// ```
    fn get<'a>(&'a self, var: &'a RLUVar<T>) -> Result<ReadGuard<'a, T>>;
}

/// [`Write<T>`] gives mutable access to synchronized value via the current managing
/// context.
pub trait Write<T>
where
    T: Clone,
{
    /// Returns an mutable [`WriteGuard`] on the value of [`RLUVar`]
    ///
    /// This function returns a mutable copy if the original value. The [`WriteGuard`]
    /// ensures that after dereferencing and writing to the value, the internal log
    /// will be updated to the most recent change
    ///
    /// # Example
    /// ```
    /// use stronghold_rlu::*;
    ///
    /// // create simple value, that should be managed by RLU
    /// let value = 6usize;
    ///
    /// // first we need to create a controller
    /// let ctrl = RLU::new();
    ///
    /// // via the controller  we create a RLUVar reference
    /// let rlu_var: RLUVar<usize> = ctrl.create(value);
    ///
    /// // we clone the reference to it to use it inside a thread
    /// let var_1 = rlu_var.clone();
    ///
    /// // via the controller we can spawn a thread safe context
    /// ctrl.execute(move |mut context| {
    ///     let mut inner = context.get_mut(&var_1)?;
    ///     let data = &mut *inner;
    ///     *data += 10;
    ///     Ok(())
    /// });
    ///
    /// assert_eq!(rlu_var.get(), 16);
    /// ```
    fn get_mut<'a>(&'a self, var: &'a RLUVar<T>) -> Result<WriteGuard<'a, T>>;
}