Open milyin opened 1 month ago
PR missing one of the required labels: {'bug', 'internal', 'breaking-change', 'enhancement', 'dependencies', 'documentation', 'new feature'}
PR missing one of the required labels: {'dependencies', 'new feature', 'breaking-change', 'enhancement', 'bug', 'documentation', 'internal'}
PR missing one of the required labels: {'breaking-change', 'bug', 'dependencies', 'new feature', 'enhancement', 'internal', 'documentation'}
PR missing one of the required labels: {'enhancement', 'internal', 'new feature', 'breaking-change', 'bug', 'dependencies', 'documentation'}
After quick discusion it was decided to reduce this update only for types actually used by callbacks
Agreed with @DenisBiryukov91 opition that the real goal is to allow user to take z_owned_bytes_t
from the sample or query or reply. It's safer to just add functionality for that, z_take_loaned
is not necessary in this case anymore
Summary of latest discussion with @DenisBiryukov91 about the issue:
The "take from loaned" functionality is necessary for C++
Explanation: C++ doesn't actually use "z_xxx_loaned_t*" types. Each C++ object is a wrapper over corresponding "owned" zenoh-c object. This works only for objects which conforms condition sizeof(z_xxx_loaned_t)==sizeof(z_xxx_owned_t)
which is true for most of zenoh-c objects (except e.g. mutexes, which are not wrapped by C++).
Internally in rust the z_owned_xxx_t
is typically Option<XXX>
and z_loaned_xxx_t
is just XXX
. When the Option uses Null Pointer Optimization (https://doc.rust-lang.org/std/option/index.html) the transmute from XXX
to Option<XXX>
is allowed, and therefore the pointer conversion from z_moved_xxx_t
to z_loaned_xxx_t
is allowed.
The problem is in conversion in opposite direction: from loaned to moved. The example of problematic sequence of operations is:
z_loaned_sample_t*
argumentz_loaned_sample_t*
is transmuted to z_owned_sample_t*
and then to C++ object reference zenoh::Sample&
for C++ callbackSample s2(std::move(sample))
. This leaves on place of original sample the None
value (in Rust representation). But if originally on Rust side it was just Sample
, not a Option<Sample>
, this causes crash: None
is not a valid value for Sample
The proposed solution: allow C++ to implement move constructor by taking important data from mutable loaned reference, keeping at the original place something "empty": dummy but valid. Thus the following operations should be defined:
z_owned_xxx_t
z_xxx_loan
: z_owned_xxx_t
-> const z_loaned_xxx_t*
z_xxx_loan_mut
: z_owned_xxx_t*
-> z_loaned_xxx_t*
z_xxx_move
: z_owned_xxx_t*
-> z_moved_xxx_t*
z_xxxx_take
: z_moved_xxx_t*
-> fills new z_owned_xxx_t
, sets original z_owned_xxx_t
to so-called "gravestone" statez_xxx_drop
: z_moved_xxx_t*
-> destruct original z_owned_xxx_t
, set it to gravestone statez_loaned_xxx_t*
-> fills new z_owned_xxx_t
, sets original z_owned_xxx_t
to "unspecified" state.The difference between "unspecified" and "gravestone" state is this:
"Gravestone" is a state of owned object which corresponds to None
in Rust for objects wrapped to Option
. It doesn't contain any meaningful data, access to it may cause segmentation fault, drop operation on it not required, but safe.
"unspecified" is a state which corresponds to some valid value in Rust (for Option-wrapped objects is always Some<...>
). It maybe safe to check it's state, if such operation is provided (like e.g. z_bytes_len
). Drop operation on it is required.
In short: new z_xxx_take_from_loaned(z_owned_xxx_t* dst, z_loaned_xxx_t* src)
operation is added for some objects.
dst
exact clone of src
src
in a "valid but unspecifed" state, like after std::move
in C++ (https://stackoverflow.com/questions/7930105/does-moving-leave-the-object-in-a-usable-state)
This update adds
z_sample_take_loaned
,z_reply_take_loaned
,z_query_take_loaned
andz_hello_take_loaned
operations on correspondingz_loaned_sample_t*
,z_loaned_reply_t*
,z_loaned_hello_t*
, andz_loaned_query_t*
.This API this is made for callbacks, which accepts data as mutable loaned references. Now user can either access the object on place or take it with
z_xxx_take_loaned
to process later.Internally this update provides guaranty that for objects supporting
take_loaned
operations the reference toOption<...>
object is converted to mutablez_loaned_xxx*
pointer. I.e. the&Sample
in converted toconst z_loaned_sample*
and&mut Option<Sample>
- toz_loaned_sample_t*
.