-
Notifications
You must be signed in to change notification settings - Fork 288
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 Bytes::try_unsplit()
#287
Comments
@abonander Shouldn't you be able to do similar thing by converting to
|
@DoumanAsh the idea is to avoid performing a copy which that path necessitates. You're not mutating the underlying bytes, just widening the slice which should be safe as long as immutable references remain to the whole buffer. |
Taking the second bytes by reference would remove the need to return it in the error case.
In cases where you could unsplit (both |
I feel like this should be easy to implement and would be pretty useful. My proposed function prototype is:
And it'd check if the shared data is the same and if they are adjacent, and return a I could get a shot at trying to implement it if you want. |
I would have had a use for the API too. I think the API proposed in the original comment makes most sense - if the unsplit worked the original Regarding the implementation: With the new vtable based approach you would likely check whether both internal pointers are equivalent and the data regions are adjacent. Then adjust the data region in the first object and call the vtable I'm unsure whether that would have any negative side effects on some buffer implementations, where the same |
Taking |
Whatever API is chosen, there will be 1 refcount decrement if successful and 0 if not successful. A move of a value doesn't change the refcount - only a clone or drop would. The merge here is the equivalent of a drop of the unused half. The thing which we merge into should be taken by |
@seanmonstar I think this would require an addition to the vtable? |
Perhaps it would. I'm glad we didn't make the vtable stuff public just yet, I really don't like that it doesn't have a way to add new optional methods like a trait does. I'm thinking of trying to adjust the design a little to not be a |
I am not sure if it really does. Although I guess a vtable function would be cleaner, since it provides a way out if we discover in the future that there are some I think even with the vtable approach we can add optional methods: In order to do that, do not grant applications access to the vtable directly, but for force them to go throug a builder: let vtable = VTableBuilder::new().set_clone(my_clone_fn).set_drop(my_drop_fn).build()` That way you can default some functions which are not explicitly set in the same way as with traits. And of course even with a some extension points there are only so much backward compatible changes we can make. E.g. adding a default implementation for |
I'm not sure this is a safe assumption. If you have two separate allocations that happen to be right next to each other in the address space, and tried to un-split them, you could erroneously think they point to a single owned allocation. I tried this out with
Oh yea, that could work too... I just don't actually see the benefit of the raw vtable approach over some
I'd expect a default implementation would just be pessimistic and assume unsplitting failed, so that would be backwards compatible. |
I think the contract is that two separate allocations also have two separate I think the only exception are "allocators" which use I think if the documentation specifies that each unique byte range must have a unique |
Similar in spirit to this would be a #[derive(Deserialize)]
struct Data {
wrapped: Bytes,
} |
Assigning this to the v0.6 milestone in order to determine if an API needs to change based on this discussion. |
Ok, looking at this, because the vtable is still private, adding I'm removing the 0.6 milestone. I also opened #437 to track questions related to the vtable. |
I think the safest/easiest approach would be to add a Does it solve all cases? No, but a consumer should be able to use it to achieve their goals. |
To clarify: If someone says The condition that @seanmonstar mentioned might be a real scenario, but there is no need to check for it. The overall operation would fail and we should return an error. This is because the clone + resize operation would fail because it would be impossible for X to have the capacity to support that. As long we do the continuity check as implemented, AND we check that capacity exists in X, this should be a safe operation. |
@Matthias247 wrote:
There is no guaranteeing that there aren't more clones of the "other" Passing For avoiding the extra increment, we can do it with just a change of |
I was able to kill two birds with the |
I headed here from #702, but dropping in to add support for a similar request. A So I have various worker threads, each hosts various producers and consumers (potentially thousands+). Each worker thread has a dedicated There are three things that can happen, from best to worst:
There's also some potential advantage to having the sending thread Anyhow, that's my story! I'm curious if you just don't have this problem. It may be specific to thread-per-core architectures where you pre-allocate buffers for each thread pair, and really do expect The larger goal, in case this sparks any creative juices, is for each ordered pair of workers to communicate serialized data, unidirectionally, without using the allocator in steady state. Currently, this is a pool of |
I see APIs have been proposed like this before but all I want is a method to try to unsplit a
Bytes
as I think that should be possible in many cases, and if it fails the user can choose to perform a copy:I'd like it to take
self
by mutable reference as that's generally more versatile and matches the signature ofBytesMut::unsplit()
.The text was updated successfully, but these errors were encountered: