diff --git a/book/src/how_it_works.md b/book/src/how_it_works.md index e335040..bc933db 100644 --- a/book/src/how_it_works.md +++ b/book/src/how_it_works.md @@ -14,9 +14,12 @@ only need the pointer to be valid (which basically means `ptr..ptr+size` should aligned. So Zngur can use the pointer to the below `data` in those functions: ```C++ -alignas(align_value) ::std::array data; +alignas(align_value) mutable ::std::array data; ``` +The `mutable` keyword is equivalent to the `UnsafeCell` in Rust. It allows modifying `const` objects (which happens with +Rust interior mutable types) without triggering UB. + To support running destructors of Rust types in C++, Zngur uses `std::ptr::drop_in_place` which has similar constraints to `read` and `write`. But to prevent double free, Zngur needs to track if a Rust type is moved out. It does this using a boolean field called `drop_flag`, which is `false` if the value doesn't need drop (it is uninitialized or moved out from) and otherwise `true`. So a C++ wrapper @@ -25,7 +28,7 @@ for a typical Rust type will look like this: ```C++ struct MultiBuf { private: - alignas(8)::std::array data; + alignas(8) mutable ::std::array data; bool drop_flag; public: diff --git a/zngur-generator/src/cpp.rs b/zngur-generator/src/cpp.rs index 44e42b3..69d41d7 100644 --- a/zngur-generator/src/cpp.rs +++ b/zngur-generator/src/cpp.rs @@ -748,7 +748,7 @@ public: r#" {{ private: - alignas({align}) ::std::array data; + alignas({align}) mutable ::std::array data; "#, )?; }