-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Borrow multiple structs mutable from State
#94
Conversation
# Conflicts: # src/framework/components.rs # src/framework/state.rs # src/framework/state/common.rs
State
State
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does look good over all, but it definitely needs more documentation.
Once it's properly documented, and the macro for convenience functions does not hamper formatting, we can merge this.
src/framework/state.rs
Outdated
($l:lifetime, $t:ty) => { | ||
/// Returns [Iterations](common::Iterations) state. | ||
pub fn iterations(self: $t) -> u32 { | ||
self.get_value::<common::Iterations>() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation seems to be a bit messed up. Furthermore, I'm tempted to implement all of this as a trait. If formatting works inside this macro, it should be okay, but if not, using a trait would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a trait has the disadvantage that MutState
requires &mut self
even for non-mutable access (because the type is inserted into the internal type set), so a trait bundling the convenience methods needs to borrow self
mut on, e.g., population_stack()
. This consequently means borrowing State
mut for population_stack()
even when it's not needed, which could be kind of annoying when accessing the stack multiple times read-only.
I guess we could implement the convenience methods for each struct separately, but this just means trading off auto-formatting on a small code snippet against duplicated code and documentation.
This is why I ultimately settled on a macro, because the convenience methods are not expected to be frequently touched, and adding a new method just means making sure exactly once that the formatting is right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm that's annoying. I don't think there is a nice way to deal with this then.
pub fn get_mut<T: CustomState>(&mut self) -> &'a mut T { | ||
let custom = self.state.get_mut::<T>() as *mut T; | ||
assert!( | ||
self.borrowed.insert(TypeId::of::<T>()), | ||
"each type can only be borrowed once" | ||
); | ||
unsafe { &mut *custom } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that every type can only be borrowed once, even if the states reference gets dropped before, should be documented clearly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I forgot a bunch of documentation in several places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that currently neither MutState
nor MultiStateTuple
are public, and thus their documentation is hidden as well.
Both |
You're right, I forgot that Edit: Added #96. |
Yeah we will have to review the documentation as a whole. But |
This was actually deliberate, as |
Unless we have a good reason to keep it private (i.e. we want to have a sealed trait, which is why Rust allows this), it should be public if it's part of our api. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
Closes #86
Adds two methods to
State
:get_multiple_mut()
(previouslyget_many()
) returns up to eight different mut refs toCustomState
's, given they are different.get_states_mut()
returns theMutState
struct, which implements pretty much the same methods asState
(exceptinsert
and the parent methods, but including the convenience methods), but allows simultaneously accessing multiple mut refs to differentCustomState
, with the restriction that eachCustomState
can only be borrowed once.Example usage of
get_multiple_mut()
can be found inAcoGeneration
, and usage ofget_states_mut()
inSimpleEvaluator
.