Skip to content
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

Merged
merged 15 commits into from
Jun 24, 2022
Merged

Conversation

Saethox
Copy link
Collaborator

@Saethox Saethox commented Jun 20, 2022

Closes #86

Adds two methods to State:

  • get_multiple_mut() (previously get_many()) returns up to eight different mut refs to CustomState's, given they are different.
  • get_states_mut() returns the MutState struct, which implements pretty much the same methods as State (except insert and the parent methods, but including the convenience methods), but allows simultaneously accessing multiple mut refs to different CustomState, with the restriction that each CustomState can only be borrowed once.

Example usage of get_multiple_mut() can be found in AcoGeneration, and usage of get_states_mut() in SimpleEvaluator.

@Saethox Saethox changed the title WIP: Borrow multiple structs mutable from State Borrow multiple structs mutable from State Jun 20, 2022
@Saethox Saethox requested a review from luleyleo June 20, 2022 10:53
Copy link
Collaborator

@luleyleo luleyleo left a 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.

Comment on lines 155 to 159
($l:lifetime, $t:ty) => {
/// Returns [Iterations](common::Iterations) state.
pub fn iterations(self: $t) -> u32 {
self.get_value::<common::Iterations>()
}
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

Comment on lines +18 to +25
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 }
}
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

@Saethox Saethox requested a review from luleyleo June 22, 2022 12:34
@luleyleo
Copy link
Collaborator

Both MutState and MultiStateTuple are still private. It's best to always compile and check the documentation to make sure all links are working and everything looks good.

@Saethox
Copy link
Collaborator Author

Saethox commented Jun 23, 2022

You're right, I forgot that framework::state is not public. Running cargo doc also revealed some other broken links and images in the documentation, so we might want to also fix that. I think an issue for reviewing the documentation in general is appropriate, as most methods and structs lack it.

Edit: Added #96.

@luleyleo
Copy link
Collaborator

Yeah we will have to review the documentation as a whole.

But MultiStateTuple is still private. Could you export that as well, then we can merge this.

@Saethox
Copy link
Collaborator Author

Saethox commented Jun 23, 2022

This was actually deliberate, as State::get_multiple_mut already has enough documentation in my opinion. Or does leaving MultiStateTuple private conflict with some visibility guideline in some way? If so, I will change it.

@luleyleo
Copy link
Collaborator

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.

Copy link
Collaborator

@luleyleo luleyleo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@Saethox Saethox merged commit 3363576 into master Jun 24, 2022
@Saethox Saethox deleted the multiple-mut-states branch June 24, 2022 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Borrow multiple structs mutable from State
2 participants