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_accessormacros:
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();
}
}