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

Featue: making len atomic #8

Open
cehteh opened this issue Sep 16, 2024 · 4 comments
Open

Featue: making len atomic #8

cehteh opened this issue Sep 16, 2024 · 4 comments

Comments

@cehteh
Copy link
Contributor

cehteh commented Sep 16, 2024

I would like to know if you are interested to merge a rather big slightly breaking change:

The .len field could be atomic with:

  • add unsafe fn HeaderVecHeader::len_add_release() incrementing the length being a atomic op
    This is unsafe because one has to hold a promised contract, see below
  • making HeaderVecHeader::len(&mut self) -> usize (note the mut, this is a breaking change)
  • adding unsafe fn HeaderVecHeader::len_acquire(&self) -> usize this is what .len() currently does, but using atomics

Alternative without breaking changes:

  • using the atomic op for .len(&self) under the hood, keeping the compatible API
  • adding a HeaderVecHeader::len_noatomic(&mut self) -> usize // or other name
    Disadvantage is that the .len() API which is what users most likely want to use/expect would have to pay the atomics cost on some platforms.

Rationale:
One can add elements within capacity and then when done increment the len atomically as long the vec stays within capacity. But adding elements needs some synchronization otherwise this will be racy. The len_add_release() is unsafe because of this. The actual synchronization is deliberately not part of the implementation here and has to be done somehow else.

Currently I roll my own allocation very similar to what this crate does in https://crates.io/crates/cowstr I would like to externalize this to another crate and yours fits my needs except for the above changes. When you like the idea I will make the proposed changes and send a PR.

@vadixidav
Copy link
Member

vadixidav commented Sep 16, 2024

I agree that it is good to have a single implementation in the ecosystem where possible. It almost seems like two different use cases appear when attempting to separately update the length. I understand that any case where this crate is used is almost certainly going to be highly performance sensitive, so being able to update that length with utmost performance is always important. I believe the right solution is likely to have two separate types, one for each of your proposed solutions. The user will choose the one that is more appropriate for their use case. I can address this soon.

If you already have the changes available or wish to contribute them, I would be happy to accept them. It is okay to make a breaking change so that each implementation has an appropriate name as needed.

@cehteh
Copy link
Contributor Author

cehteh commented Sep 16, 2024

dunno if you really need 2 implementations because AtomicBool has .get_mut() which allows you to mutate the the atomic in a optimized non atomic way that is pretty well optimized. Only for getting the len() it needs a atomic and a non atomic variant, the actual naming might be bikeshedding. Your decision if that qualifies to make a complete new variant. IMO it would benefit to have both in once because under certain conditions (like one has a &mut self) non atomic access is always possible while for the same kind of object one has a shared variant where the length needs to be accessed atomically. I also deliberately left out a atomic decrement of the length. as this definitely will be racy.

@vadixidav
Copy link
Member

I might actually need to see what the changes would look like then. I am willing to merge regardless, but if we need to create two variants I can do that myself if you check the checkbox in the PR that says "allow maintainers to make edits."

@cehteh
Copy link
Contributor Author

cehteh commented Sep 17, 2024 via email

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

No branches or pull requests

2 participants