-
Notifications
You must be signed in to change notification settings - Fork 370
Add raw array pointer types #496
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
Merged
Merged
8000
Show file tree
Hide file tree
Nov 19, 2018
Sep 28, 2018
Sep 28, 2018
Sep 28, 2018
Sep 28, 2018
Nov 19, 2018
Sep 28, 2018
Nov 19, 2018
Nov 19, 2018
Nov 28, 2018
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
355b153
Make do_collapse_axis return offset instead of performing it
jturner314 ebf864f
Add DataRaw and DataRawMut traits
jturner314 2a98148
Add RawArrayView and RawArrayViewMut
jturner314 0a7fafd
Add conversions to/from RawArrayView(Mut)
jturner314 8baa1cc
Relax constraints on ArrayBase methods
jturner314 4b91c6b
Remove duplication in from_shape_ptr and split_at
jturner314 e2fcf22
Add DataRawClone and relax Clone implementation
jturner314 6ef3b48
Remove deref_view and deref_view_mut
jturner314 c81ccdd
Deprecate the DataClone trait
jturner314 218bb88
Rename DataRaw* traits to RawData*
jturner314 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ use std::sync::Arc; | |
| use { | ||
| ArrayBase, | ||
| Dimension, | ||
| RawViewRepr, | ||
| ViewRepr, | ||
| OwnedRepr, | ||
| OwnedRcRepr, | ||
|
|
@@ -22,92 +23,177 @@ use { | |
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// ***Note:*** `Data` is not an extension interface at this point. | ||
| /// For an array that meets the invariants of the `ArrayBase` type. This trait | ||
| /// does not imply any ownership or lifetime; pointers to elements in the array | ||
| /// may not be safe to dereference. | ||
| /// | ||
| /// ***Note:*** `RawData` is not an extension interface at this point. | ||
| /// Traits in Rust can serve many different roles. This trait is public because | ||
| /// it is used as a bound on public methods. | ||
| pub unsafe trait Data : Sized { | ||
| pub unsafe trait RawData : Sized { | ||
| /// The array element type. | ||
| type Elem; | ||
|
|
||
| #[doc(hidden)] | ||
| // This method is only used for debugging | ||
| fn _data_slice(&self) -> &[Self::Elem]; | ||
| fn _data_slice(&self) -> Option<&[Self::Elem]>; | ||
|
|
||
| private_decl!{} | ||
| } | ||
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// For an array with writable elements. | ||
| /// | ||
| /// ***Internal trait, see `RawData`.*** | ||
| pub unsafe trait RawDataMut : RawData { | ||
| /// If possible, ensures that the array has unique access to its data. | ||
| /// | ||
| /// If `Self` provides safe mutable access to array elements, then it | ||
| /// **must** panic or ensure that the data is unique. | ||
| #[doc(hidden)] | ||
| fn try_ensure_unique<D>(&mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension; | ||
|
|
||
| /// If possible, returns whether the array has unique access to its data. | ||
| /// | ||
| /// If `Self` provides safe mutable access to array elements, then it | ||
| /// **must** return `Some(_)`. | ||
| #[doc(hidden)] | ||
| fn try_is_unique(&mut self) -> Option<bool>; | ||
| } | ||
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// An array representation that can be cloned. | ||
| /// | ||
| /// ***Internal trait, see `RawData`.*** | ||
| pub unsafe trait RawDataClone : RawData { | ||
| #[doc(hidden)] | ||
| /// Unsafe because, `ptr` must point inside the current storage. | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem); | ||
|
|
||
| #[doc(hidden)] | ||
| unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem { | ||
| let (data, ptr) = other.clone_with_ptr(ptr); | ||
| *self = data; | ||
| ptr | ||
| } | ||
| } | ||
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// For an array with elements that can be accessed with safe code. | ||
| /// | ||
| /// ***Internal trait, see `RawData`.*** | ||
| pub unsafe trait Data : RawData { | ||
| /// Converts the array to a uniquely owned array, cloning elements if necessary. | ||
| #[doc(hidden)] | ||
| fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
| Self::Elem: Clone, | ||
| D: Dimension; | ||
|
|
||
| private_decl!{} | ||
| } | ||
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// For an array with writable elements. | ||
| /// For an array with writable elements that can be accessed with safe code. | ||
| /// | ||
| /// ***Internal trait, see `Data`.*** | ||
| pub unsafe trait DataMut : Data { | ||
| // | ||
| // # For implementers | ||
| // | ||
| // If you implement the `DataMut` trait, you are guaranteeing that the | ||
| // `RawDataMut::try_ensure_unique` implementation always panics or ensures that | ||
| // the data is unique. You are also guaranteeing that `try_is_unique` always | ||
| // returns `Some(_)`. | ||
| pub unsafe trait DataMut : Data + RawDataMut { | ||
| /// Ensures that the array has unique access to its data. | ||
| #[doc(hidden)] | ||
| #[inline] | ||
| fn ensure_unique<D>(&mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension | ||
| { } | ||
| fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension | ||
| { | ||
| Self::try_ensure_unique(self_) | ||
| } | ||
|
|
||
| /// Returns whether the array has unique access to its data. | ||
| #[doc(hidden)] | ||
| #[inline] | ||
| fn is_unique(&mut self) -> bool { | ||
| true | ||
| self.try_is_unique().unwrap() | ||
| } | ||
| } | ||
|
|
||
| /// Array representation trait. | ||
| /// | ||
| /// An array representation that can be cloned. | ||
| /// An array representation that can be cloned and allows elements to be | ||
| /// accessed with safe code. | ||
| /// | ||
| /// ***Internal trait, see `Data`.*** | ||
| pub unsafe trait DataClone : Data { | ||
| #[doc(hidden)] | ||
| /// Unsafe because, `ptr` must point inside the current storage. | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem); | ||
| #[deprecated(note="use `Data + RawDataClone` instead", since="0.13")] | ||
| pub trait DataClone : Data + RawDataClone {} | ||
|
|
||
| #[doc(hidden)] | ||
| unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem { | ||
| let (data, ptr) = other.clone_with_ptr(ptr); | ||
| *self = data; | ||
| ptr | ||
| #[allow(deprecated)] | ||
| impl<T> DataClone for T where T: Data + RawDataClone {} | ||
|
|
||
| unsafe impl<A> RawData for RawViewRepr<*const A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| None | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<A> Data for OwnedArcRepr<A> { | ||
| unsafe impl<A> RawDataClone for RawViewRepr<*const A> { | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { | ||
| (*self, ptr) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> RawData for RawViewRepr<*mut A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> &[A] { | ||
| &self.0 | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| None | ||
| } | ||
| fn into_owned<D>(mut self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
| A: Clone, | ||
| D: Dimension, | ||
| { | ||
| Self::ensure_unique(&mut self_); | ||
| let data = OwnedRepr(Arc::try_unwrap(self_.data.0).ok().unwrap()); | ||
| ArrayBase { | ||
| data: data, | ||
| ptr: self_.ptr, | ||
| dim: self_.dim, | ||
| strides: self_.strides, | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<A> RawDataMut for RawViewRepr<*mut A> { | ||
| #[inline] | ||
| fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension | ||
| {} | ||
|
|
||
| #[inline] | ||
| fn try_is_unique(&mut self) -> Option<bool> { | ||
| None | ||
| } | ||
| } | ||
|
|
||
| D0B4 | unsafe impl<A> RawDataClone for RawViewRepr<*mut A> { | |
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { | ||
| (*self, ptr) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> RawData for OwnedArcRepr<A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| Some(&self.0) | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| // NOTE: Copy on write | ||
| unsafe impl<A> DataMut for OwnedArcRepr<A> | ||
| where A: Clone | ||
| unsafe impl<A> RawDataMut for OwnedArcRepr<A> | ||
| where | ||
| A: Clone, | ||
| { | ||
| fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>) | ||
| fn try_ensure_unique<D>(self_: &mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension | ||
| { | ||
|
|
@@ -136,23 +222,59 @@ unsafe impl<A> DataMut for OwnedArcRepr<A> | |
| } | ||
| } | ||
|
|
||
| fn is_unique(&mut self) -> bool { | ||
| Arc::get_mut(&mut self.0).is_some() | ||
| fn try_is_unique(&mut self) -> Option<bool> { | ||
| Some(Arc::get_mut(&mut self.0).is_some()) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> DataClone for OwnedArcRepr<A> { | ||
| unsafe impl<A> Data for OwnedArcRepr<A> { | ||
| fn into_owned<D>(mut self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
| A: Clone, | ||
| D: Dimension, | ||
| { | ||
| Self::ensure_unique(&mut self_); | ||
| let data = OwnedRepr(Arc::try_unwrap(self_.data.0).ok().unwrap()); | ||
| ArrayBase { | ||
| data: data, | ||
| ptr: self_.ptr, | ||
| dim: self_.dim, | ||
| strides: self_.strides, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> DataMut for OwnedArcRepr<A> where A: Clone {} | ||
|
|
||
| unsafe impl<A> RawDataClone for OwnedArcRepr<A> { | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { | ||
| // pointer is preserved | ||
| (self.clone(), ptr) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> Data for OwnedRepr<A> { | ||
| unsafe impl<A> RawData for OwnedRepr<A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> &[A] { | ||
| &self.0 | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| Some(&self.0) | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<A> RawDataMut for OwnedRepr<A> { | ||
| #[inline] | ||
| fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension | ||
| {} | ||
|
|
||
| #[inline] | ||
| fn try_is_unique(&mut self) -> Option<bool> { | ||
| Some(true) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<A> Data for OwnedRepr<A> { | ||
| #[inline] | ||
| fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
|
|
@@ -161,12 +283,11 @@ unsafe impl<A> Data for OwnedRepr<A> { | |
| { | ||
| self_ | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<A> DataMut for OwnedRepr<A> { } | ||
|
|
||
| unsafe impl<A> DataClone for OwnedRepr<A> | ||
| unsafe impl<A> RawDataClone for OwnedRepr<A> | ||
| where A: Clone | ||
| { | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { | ||
|
D0B4
|
@@ -192,40 +313,58 @@ unsafe impl<A> DataClone for OwnedRepr<A> | |
| } | ||
| } | ||
|
|
||
| unsafe impl<'a, A> Data for ViewRepr<&'a A> { | ||
| unsafe impl<'a, A> RawData for ViewRepr<&'a A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> &[A] { | ||
| &[] | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| None | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<'a, A> Data for ViewRepr<&'a A> { | ||
| fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
| Self::Elem: Clone, | ||
| D: Dimension, | ||
| { | ||
| self_.to_owned() | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<'a, A> DataClone for ViewRepr<&'a A> { | ||
| unsafe impl<'a, A> RawDataClone for ViewRepr<&'a A> { | ||
| unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { | ||
| (*self, ptr) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<'a, A> Data for ViewRepr<&'a mut A> { | ||
| unsafe impl<'a, A> RawData for ViewRepr<&'a mut A> { | ||
| type Elem = A; | ||
| fn _data_slice(&self) -> &[A] { | ||
| &[] | ||
| fn _data_slice(&self) -> Option<&[A]> { | ||
| None | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<'a, A> RawDataMut for ViewRepr<&'a mut A> { | ||
| #[inline] | ||
| fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>) | ||
| where Self: Sized, | ||
| D: Dimension {} | ||
|
|
||
| #[inline] | ||
| fn try_is_unique(&mut self) -> Option<bool> { | ||
| Some(true) | ||
| } | ||
| } | ||
|
|
||
| unsafe impl<'a, A> Data for ViewRepr<&'a mut A> { | ||
| fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D> | ||
| where | ||
| Self::Elem: Clone, | ||
| D: Dimension, | ||
| { | ||
| self_.to_owned() | ||
| } | ||
| private_impl!{} | ||
| } | ||
|
|
||
| unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> { } | ||
|
|
@@ -250,7 +389,7 @@ pub unsafe trait DataOwned : Data { | |
| /// A representation that is a lightweight view. | ||
| /// | ||
| /// ***Internal trait, see `Data`.*** | ||
| pub unsafe trait DataShared : Clone + DataClone { } | ||
| pub unsafe trait DataShared : Clone + Data + RawDataClone { } | ||
|
|
||
| unsafe impl<A> DataShared for OwnedRcRepr<A> {} | ||
| unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {} | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I think we can be without this trait, and just use DataClone?
Cloneis the only consumer of the traitThere 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.
In current
ndarray,DataClonehas aDatabound. If we want to be able to cloneArrayPtr/ArrayPtrMut, this is too restrictive given only the current implementation ofCloneforArrayBase. Possible alternatives to the approach in this PR:Don't add a
DataRawClonetrait; instead, implementCloneindividually forArrayPtrandArrayPtrMut. That would be inconsistent and would prevent code with just aDataClonebound from being able to cloneArrayPtrandArrayPtrMut.With a breaking change, though, we could get rid of
DataCloneentirely and just implementCloneindividually forArcArray,Array,ArrayView,ArrayPtr, andArrayPtrMut. This actually seems pretty nice, but it does make writing generic code more difficult. (In user code, the bound to allowarray.clone()would have to beArrayBase<S, D>: Cloneinstead ofS: DataRawClone.)Add the
DataRawClonetrait and remove theDataClonetrait. That would work but would be a breaking change.Fwiw,
DataClonedoes have a small amount of utility as the combination ofDataandDataRawClone, but I agree it does seem like unnecessary complication.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.
(2) I think a breaking change is ok. We have lots of them queued? We should get on to merging them as soon as 0.12.1 is released (and I can do the releasing if you want).
I'd hope it has very little impact on users, but maybe I underestimate how much these representation traits are used?
I'd use the name
DataClonefor the new trait.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.
The only thing that I don't like about this is consistency of naming with the other data traits, especially
DataMutvs.DataRawMut. I was naming traits without aDataboundDataRaw*and traits with aDataboundData*.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.
Good point. We still should use only one trait if we don't need 2, we could use the name DataRawClone and let DataClone be a deprecated reexport of it.
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.
DataClone could be a trait alias of DataRawClone + Data? That's a new Rust feature we can transition to.
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.
Woah, I had no idea trait aliases were a thing. They look very convenient.
I've added a commit deprecating
DataClone. We can switchDataCloneto a trait alias once they're available on stable.