Module mutable_state

Module mutable_state 

Source
Expand description

Macros used with struct containing an immutable state and a RwLock to a mutable state.

These macros define a new type of read and write guards that allow access to both the mutable and immutable state. To use it, one must:

  • Define the main struct (e.g. Foo) for the object with the immutable state.
  • Define a struct for the mutable state (e.g. FooMutableState).
  • Have a RwLock<> in the main struct for the mutable state (e.g. mutable_state: RwLock<FooMutableState>).
  • In the implementation of the main struct, add a call to the state_accessor macros:
impl Foo {
  state_accessor!(Foo, mutable_state);
}
  • Write the method on the guards using the state_implementation macro:
#[apply(state_implementation!)]
impl FooMutableState<Base=Foo> {
    // Some comment
    fn do_something(&self) -> i32 {
        0
    }
}

§Complete example:

pub struct FooMutableState {
    y: i32,
}

pub struct Foo {
    x: i32,
    mutable_state: RwLock<FooMutableState>,
}

impl Foo {
    fn new() -> Self {
        Self { x: 2, mutable_state: RwLock::new(FooMutableState { y: 3 }) }
    }

    state_accessor!(Foo, mutable_state);
}

#[attr(state_implementation!)]
impl FooMutableState<Base=Foo> {
    // Some comment
    fn x_and_y(&self) -> i32 {
        self.base.x + self.y
    }
    /// Some rustdoc.
    pub fn pub_x_and_y(&self) -> i32 {
        self.x_and_y()
    }
    fn do_something(&self) {}
    fn set_y(&mut self, other_y: i32) {
        self.y = other_y;
    }
    pub fn pub_set_y(&mut self, other_y: i32) {
        self.set_y(other_y)
    }
    fn do_something_mutable(&mut self) {
        self.do_something();
    }

    #[allow(dead_code)]
    pub fn with_lifecycle<'a>(&self, _n: &'a u32) {}
    #[allow(dead_code)]
    pub fn with_type<T>(&self, _n: &T) {}
    #[allow(dead_code)]
    pub fn with_lifecycle_and_type<'a, T>(&self, _n: &'a T) {}
    #[allow(dead_code)]
    pub fn with_lifecycle_on_self<'a, T>(&'a self, _n: &'a T) {}
}

§Generated code

pub struct FooMutableState {
    y: i32,
}
pub struct Foo {
    x: i32,
    mutable_state: RwLock<FooMutableState>,
}
impl Foo {
    fn new() -> Self {
        Self {
            x: 2,
            mutable_state: RwLock::new(FooMutableState { y: 3 }),
        }
    }

    #[allow(dead_code)]
    pub fn read<'a>(self: &'a Foo) -> FooReadGuard<'a> {
        ReadGuard::new(self, self.mutable_state.read())
    }
    #[allow(dead_code)]
    pub fn write<'a>(self: &'a Foo) -> FooWriteGuard<'a> {
        WriteGuard::new(self, self.mutable_state.write())
    }
}

#[allow(dead_code)]
pub type FooReadGuard<'guard_lifetime> = ReadGuard<'guard_lifetime, Foo, FooMutableState>;
#[allow(dead_code)]
pub type FooWriteGuard<'guard_lifetime> = WriteGuard<'guard_lifetime, Foo, FooMutableState>;
#[allow(dead_code)]
pub type FooStateRef<'ref_lifetime> = StateRef<'ref_lifetime, Foo, FooMutableState>;
#[allow(dead_code)]
pub type FooStateMutRef<'ref_lifetime> = StateMutRef<'ref_lifetime, Foo, FooMutableState>;

impl<'guard, G: 'guard + std::ops::Deref<Target = FooMutableState>> Guard<'guard, Foo, G> {
    fn x_and_y(&self) -> i32 {
        self.base.x + self.y
    }
    /// Some rustdoc.
    pub fn pub_x_and_y(&self) -> i32 {
        self.x_and_y()
    }
    fn do_something(&self) {}
    #[allow(dead_code)]
    pub fn with_lifecycle<'a>(&self, _n: &'a u32) {}
    #[allow(dead_code)]
    pub fn with_type<T>(&self, _n: &T) {}
    #[allow(dead_code)]
    pub fn with_lifecycle_and_type<'a, T>(&self, _n: &'a T) {}
    #[allow(dead_code)]
    pub fn with_lifecycle_on_self<'a, T>(&'a self, _n: &'a T) {}
}

impl<'guard, G: 'guard + std::ops::DerefMut<Target = FooMutableState>> Guard<'guard, Foo, G> {
    fn set_y(&mut self, other_y: i32) {
        self.y = other_y;
    }
    pub fn pub_set_y(&mut self, other_y: i32) {
        self.set_y(other_y)
    }
    fn do_something_mutable(&mut self) {
        self.do_something();
    }
}

Structs§

Guard

Type Aliases§

ReadGuard
StateMutRef
StateRef
WriteGuard