-
Notifications
You must be signed in to change notification settings - Fork 35
Add abomonation instance for Arc<T> #35
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ use std::io::Write; // for bytes.write_all; push_all is unstable and extend is s | |
| use std::io::Result as IOResult; | ||
| use std::marker::PhantomData; | ||
| use std::num::*; | ||
| use std::sync::Arc; | ||
|
|
||
| pub mod abomonated; | ||
|
|
||
|
|
@@ -534,6 +535,36 @@ impl<T: Abomonation> Abomonation for Box<T> { | |
| } | ||
| } | ||
|
|
||
| impl<T: Abomonation + 'static + Sized + Unpin> Abomonation for Arc<T> { | ||
| #[inline] | ||
| unsafe fn entomb<W: std::io::Write>(&self, write: &mut W) -> std::io::Result<()> { | ||
| /* Since the value T has not yet been seen by abomonate (it is behind a pointer) | ||
| * we need to fully encode it. | ||
| */ | ||
| encode(self.as_ref(), write) | ||
| } | ||
| #[inline] | ||
| unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { | ||
| use std::ptr; | ||
| /* The idea here is to construct a new Arc<T> from the entombed bytes. | ||
| * The state of this ArcVal upon entry of this function contains only an invalid | ||
| * pointer to an ArcInner that we need to dispose of without trying to run | ||
| * its destructor (which would panic). | ||
| */ | ||
| let (value, bytes) = decode::<T>(bytes)?; | ||
| // value is just a reference to the first part of old bytes, so move it into a new Arc | ||
| let arc = Arc::new(ptr::read(value)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we lift the bytes from the underlying slice and move them into the ArcInner, i.e. we move the value of type
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might be the problematic moment. Something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, that’s evil! So the only correct implementation would be to require |
||
| // now swap the fresh arc into its place ... | ||
| let garbage = std::mem::replace(self, arc); | ||
| // ... and forget about the old one | ||
| mem::forget(garbage); | ||
| Some(bytes) | ||
| } | ||
| fn extent(&self) -> usize { | ||
| std::mem::size_of::<T>() + self.as_ref().extent() | ||
| } | ||
| } | ||
|
|
||
| // This method currently enables undefined behavior, by exposing padding bytes. | ||
| #[inline] unsafe fn typed_to_bytes<T>(slice: &[T]) -> &[u8] { | ||
| std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>()) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@frankmcsherry Here
valuecontains a reference to aT. SinceT: 'staticthis structure cannot contain non-static references (but it could contain boxes). My understanding is that T can only directly referencebytesby unsafely reinterpreting a reference as a box or equivalently by transmuting a lifetime to'static. Is my assumption correct that such behaviour violates the contract of Abomonation?