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

Queue iterator no longer takes reference to flash #66

Closed
wants to merge 1 commit into from

Conversation

lulf
Copy link
Contributor

@lulf lulf commented Oct 30, 2024

Apologies for just dumping this PR without discussion first, but I wanted to validate the idea anyway before raising the PR, hopefully making it clearer what API i desire.

This permits more flexible use of the iterator, for instance if needing to perform flash operations based on some error while iterating. In the current API, the flash is held exclusively by the iterator, which prevents reading and/or writing to flash (in some unrelated region) while iterating.

This permits more flexible use of the iterator when only temporary
references to the flash can be provided, allowing it to be owned
by other types that do further processing on iterator entries.
@lulf lulf force-pushed the iter-queue-flash branch from 96615f0 to 13a0ac5 Compare October 30, 2024 12:26
@diondokter
Copy link
Collaborator

Hi, no worries!

Interesting. I see your point. The entire API doesn't hold on to the flash for the same reason, but yeah I guess the iterator is the exception.

The only downside when getting back the flash is that it could allow the user to make changes to the flash while the iterator is still making assumptions about it. This is less the case with the rest of the API. Though I guess the cache invalidates that.

So... I think we should do this.
Let me do a review.

@lulf
Copy link
Contributor Author

lulf commented Oct 30, 2024

Hey, another idea that occured to me. How about being able to consume the iterator and return the flash reference?

This should ensure that the iterator isn't broken, and allows the error handling condition which is my primary reason.

@diondokter
Copy link
Collaborator

How is that better than just dropping the iterator? If you do that you should be able to regain access to the flash from the borrow checker.

Comment on lines 198 to 199
/// after you've seen the contents.
pub async fn iter<'s, S: NorFlash, CI: CacheImpl>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe add a line of doc here to explain that you shouldn't hold on to the iterator if you're making changes to the flash it's iterating over.

Comment on lines +473 to 475
pub async fn pop<S>(self, flash: &mut S) -> Result<&'d mut [u8], Error<S::Error>>
where
S: MultiwriteNorFlash,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a bit weird to me... I feel like the entry should carry the flash reference the user gave in the iterator next function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm having second thoughts about these changes. I see why you'd want that, but on the other hand it is really the same case of needing to use the flash after looking at the entry data.

Since I've been able to work around the original API for now, I'm wondering if it's best if we leave this PR in the thinking box for a while (I can close it for now), because I kind of like the original API not handing out a footgun.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah let's wait a bit. I'm not the one in need of these changes right now.

@lulf
Copy link
Contributor Author

lulf commented Oct 30, 2024

How is that better than just dropping the iterator? If you do that you should be able to regain access to the flash from the borrow checker.

Because I can't hold a &mut F flash to the flash while holding the iterator in my type that wraps the QueueIterator, so I would need go outside the scope of my wrapped type, if that make sense.

@lulf
Copy link
Contributor Author

lulf commented Oct 30, 2024

At the moment, my code ends up like this:

    let mut it = iter(&mut self.flash, FLASH_RANGE, &mut self.cache).await?;
    MyWrappedIterator {
        it
    }

impl MyWrappedIterator {
    async fn next(&mut self) {
        match self.it.next(..).await {
            Err(e) => {
                // No way to get the flash handle inside my type
            }
            Ok(_) => {}
        }
    }
}

@diondokter
Copy link
Collaborator

At the moment, my code ends up like this:

    let mut it = iter(&mut self.flash, FLASH_RANGE, &mut self.cache).await?;
    MyWrappedIterator {
        it
    }

impl MyWrappedIterator {
    async fn next(&mut self) {
        match self.it.next(..).await {
            Err(e) => {
                // No way to get the flash handle inside my type
            }
            Ok(_) => {}
        }
    }
}

Ah ok! Hmmm yeah...

Then there are more options even. For example, the flash could be given out in the E of the result next to the error. Though that would be at the cost of not being able to use the ? operator.

But I don't see how this would work when you move the flash out of the iterator in your case because your next function wouldn't support that (as is)...

I think keeping the flash separate from the iterator is a fine compromise, so your original PR can stay (with my review comments)

@lulf lulf closed this Oct 30, 2024
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.

2 participants