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

Add support for initialising the pool to some value and allow allocating uninitialized boxes. #7

Closed
wants to merge 7 commits into from

Conversation

Frostie314159
Copy link

Hi,
this PR adds support for initializing the pool to some default value and allocating uninitialized boxes.
In my project, I want to use this for having a pool of fixed size buffers, for TX/RX of Wi-Fi frames, in my use case, it would incur a significant performance overhead, to clear the buffer.
I also expanded the docs a bit, to help people using this library for the first time.

@Frostie314159
Copy link
Author

I also fixed some clippy warnings, by adding safety comments to the user facing API:

@danielstuart14
Copy link

danielstuart14 commented Aug 16, 2024

Idk about this.
In my opinion, the item should always be initialized when allocating, but I understand your performance necessity.

In this case, instead of providing a default initial value on the macro, wouldn't it be better to just expose the MaybeUninit cell from the pool when calling new_uninit? As the function is already unsafe, I guess it would make more sense.

Also, maybe this should be behind an optional feature flag. I wouldn't want people using it without great reason.

@Frostie314159
Copy link
Author

I'm going to remove the default initial value again, since new_uninit already implies, that the memory wasn't necessarily initialized. However, I don't think, we should expose the inner MaybeUninit, since that would allow all sorts of shenanigans and the Box still automatically frees the memory.

@Dirbaio
Copy link
Member

Dirbaio commented Aug 17, 2024

This is returning a Box that is uninitialized, but there's no type-level indication that it is. For example you can Deref/DerefMut it and obtain a & or &mut to the contents that are uninitialized, which is immediate undefined behavior. Creating a & to uninitialized data is instant undefined behavior even if you never read from it.

In your example you're doing *buffer = 0xf00dbabeu32; to initialize it. That's undefined behavior, the * is doing a deref which produces a &mut. The only sound way to initialize is through raw pointers.

Due to this, I think the new_uninit() API is not ideal. It's too easy to misuse.

Also, you can already achieve this without API changes by creating a pool of MaybeUninit<T>, so new_uninit() is not needed.

@Frostie314159
Copy link
Author

That's a good point.
I'm gonna close this and use your suggestion.

@Frostie314159
Copy link
Author

This might be off topic, but wouldn't this be valid for a byte slice? Since a byte slice can't hold invalid data.

@Dirbaio
Copy link
Member

Dirbaio commented Aug 17, 2024

in the rust abstract machine a byte can have 257 possible values. 0-255 and "uninitialized". Handling uninitialized bytes is UB. You don't get "any random byte", you get actual UB.

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.

3 participants