Skip to content

Commit d02b757

Browse files
committed
FIX: Use Partial instead of PartialArray
Partial is just a contiguous slice, and much simpler than PartialArray; Partial is all that's needed, because the area written will always be contiguous.
1 parent 8ed9ac3 commit d02b757

File tree

5 files changed

+104
-225
lines changed

5 files changed

+104
-225
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ mod linalg_traits;
176176
mod linspace;
177177
mod logspace;
178178
mod numeric_util;
179+
mod partial;
179180
mod shape_builder;
180181
#[macro_use]
181182
mod slice;

src/parallel/impl_par_methods.rs

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use crate::parallel::prelude::*;
55
use crate::parallel::par::ParallelSplits;
66
use super::send_producer::SendProducer;
77

8+
use crate::partial::Partial;
9+
810
/// # Parallel methods
911
///
1012
/// These methods require crate feature `rayon`.
@@ -163,76 +165,3 @@ zip_impl! {
163165
[true P1 P2 P3 P4 P5],
164166
[false P1 P2 P3 P4 P5 P6],
165167
}
166-
167-
/// Partial is a partially written contiguous slice of data;
168-
/// it is the owner of the elements, but not the allocation,
169-
/// and will drop the elements on drop.
170-
#[must_use]
171-
pub(crate) struct Partial<T> {
172-
/// Data pointer
173-
ptr: *mut T,
174-
/// Current length
175-
len: usize,
176-
}
177-
178-
impl<T> Partial<T> {
179-
/// Create an empty partial for this data pointer
180-
///
181-
/// Safety: Unless ownership is released, the
182-
/// Partial acts as an owner of the slice of data (not the allocation);
183-
/// and will free the elements on drop; the pointer must be dereferenceable
184-
/// and the `len` elements following it valid.
185-
pub(crate) unsafe fn new(ptr: *mut T) -> Self {
186-
Self {
187-
ptr,
188-
len: 0,
189-
}
190-
}
191-
192-
pub(crate) fn stub() -> Self {
193-
Self { len: 0, ptr: 0 as *mut _ }
194-
}
195-
196-
pub(crate) fn is_stub(&self) -> bool {
197-
self.ptr.is_null()
198-
}
199-
200-
/// Release Partial's ownership of the written elements, and return the current length
201-
pub(crate) fn release_ownership(mut self) -> usize {
202-
let ret = self.len;
203-
self.len = 0;
204-
ret
205-
}
206-
207-
/// Merge if they are in order (left to right) and contiguous.
208-
/// Skips merge if T does not need drop.
209-
pub(crate) fn try_merge(mut left: Self, right: Self) -> Self {
210-
if !std::mem::needs_drop::<T>() {
211-
return left;
212-
}
213-
// Merge the partial collect results; the final result will be a slice that
214-
// covers the whole output.
215-
if left.is_stub() {
216-
right
217-
} else if left.ptr.wrapping_add(left.len) == right.ptr {
218-
left.len += right.release_ownership();
219-
left
220-
} else {
221-
// failure to merge; this is a bug in collect, so we will never reach this
222-
debug_assert!(false, "Partial: failure to merge left and right parts");
223-
left
224-
}
225-
}
226-
}
227-
228-
unsafe impl<T> Send for Partial<T> where T: Send { }
229-
230-
impl<T> Drop for Partial<T> {
231-
fn drop(&mut self) {
232-
if !self.ptr.is_null() {
233-
unsafe {
234-
std::ptr::drop_in_place(std::slice::from_raw_parts_mut(self.ptr, self.len));
235-
}
236-
}
237-
}
238-
}

src/partial.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2020 bluss and ndarray developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use std::ptr;
10+
11+
/// Partial is a partially written contiguous slice of data;
12+
/// it is the owner of the elements, but not the allocation,
13+
/// and will drop the elements on drop.
14+
#[must_use]
15+
pub(crate) struct Partial<T> {
16+
/// Data pointer
17+
ptr: *mut T,
18+
/// Current length
19+
pub(crate) len: usize,
20+
}
21+
22+
impl<T> Partial<T> {
23+
/// Create an empty partial for this data pointer
24+
///
25+
/// ## Safety
26+
///
27+
/// Unless ownership is released, the Partial acts as an owner of the slice of data (not the
28+
/// allocation); and will free the elements on drop; the pointer must be dereferenceable and
29+
/// the `len` elements following it valid.
30+
///
31+
/// The Partial has an accessible length field which must only be modified in trusted code.
32+
pub(crate) unsafe fn new(ptr: *mut T) -> Self {
33+
Self {
34+
ptr,
35+
len: 0,
36+
}
37+
}
38+
39+
#[cfg(feature = "rayon")]
40+
pub(crate) fn stub() -> Self {
41+
Self { len: 0, ptr: 0 as *mut _ }
42+
}
43+
44+
#[cfg(feature = "rayon")]
45+
pub(crate) fn is_stub(&self) -> bool {
46+
self.ptr.is_null()
47+
}
48+
49+
/// Release Partial's ownership of the written elements, and return the current length
50+
pub(crate) fn release_ownership(mut self) -> usize {
51+
let ret = self.len;
52+
self.len = 0;
53+
ret
54+
}
55+
56+
#[cfg(feature = "rayon")]
57+
/// Merge if they are in order (left to right) and contiguous.
58+
/// Skips merge if T does not need drop.
59+
pub(crate) fn try_merge(mut left: Self, right: Self) -> Self {
60+
if !std::mem::needs_drop::<T>() {
61+
return left;
62+
}
63+
// Merge the partial collect results; the final result will be a slice that
64+
// covers the whole output.
65+
if left.is_stub() {
66+
right
67+
} else if left.ptr.wrapping_add(left.len) == right.ptr {
68+
left.len += right.release_ownership();
69+
left
70+
} else {
71+
// failure to merge; this is a bug in collect, so we will never reach this
72+
debug_assert!(false, "Partial: failure to merge left and right parts");
73+
left
74+
}
75+
}
76+
}
77+
78+
unsafe impl<T> Send for Partial<T> where T: Send { }
79+
80+
impl<T> Drop for Partial<T> {
81+
fn drop(&mut self) {
82+
if !self.ptr.is_null() {
83+
unsafe {
84+
ptr::drop_in_place(std::slice::from_raw_parts_mut(self.ptr, self.len));
85+
}
86+
}
87+
}
88+
}

src/zip/mod.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#[macro_use]
1010
mod zipmacro;
11-
mod partial_array;
1211

1312
use std::mem::MaybeUninit;
1413

@@ -17,13 +16,12 @@ use crate::AssignElem;
1716
use crate::IntoDimension;
1817
use crate::Layout;
1918
use crate::NdIndex;
19+
use crate::partial::Partial;
2020

2121
use crate::indexes::{indices, Indices};
2222
use crate::layout::{CORDER, FORDER};
2323
use crate::split_at::{SplitPreference, SplitAt};
2424

25-
use partial_array::PartialArray;
26-
2725
/// Return if the expression is a break value.
2826
macro_rules! fold_while {
2927
($e:expr) => {
@@ -1070,21 +1068,28 @@ macro_rules! map_impl {
10701068
/// inputs.
10711069
///
10721070
/// If all inputs are c- or f-order respectively, that is preserved in the output.
1073-
pub fn apply_collect<R>(self, f: impl FnMut($($p::Item,)* ) -> R) -> Array<R, D>
1071+
pub fn apply_collect<R>(self, mut f: impl FnMut($($p::Item,)* ) -> R) -> Array<R, D>
10741072
{
10751073
// Make uninit result
10761074
let mut output = self.uninitalized_for_current_layout::<R>();
10771075
if !std::mem::needs_drop::<R>() {
10781076
// For elements with no drop glue, just overwrite into the array
10791077
self.apply_assign_into(&mut output, f);
10801078
} else {
1081-
// For generic elements, use a proxy that counts the number of filled elements,
1079+
// For generic elements, use a Partial to counts the number of filled elements,
10821080
// and can drop the right number of elements on unwinding
10831081
unsafe {
1084-
PartialArray::scope(output.view_mut(), move |partial| {
1085-
debug_assert_eq!(partial.layout().tendency() >= 0, self.layout_tendency >= 0);
1086-
self.apply_assign_into(partial, f);
1082+
let mut output = output.raw_view_mut().cast::<R>();
1083+
let mut partial = Partial::new(output.as_mut_ptr());
1084+
let partial_ref = &mut partial;
1085+
debug_assert!(output.is_contiguous());
1086+
debug_assert_eq!(output.layout().tendency() >= 0, self.layout_tendency >= 0);
1087+
self.and(output)
1088+
.apply(move |$($p, )* output_: *mut R| {
1089+
output_.write(f($($p ),*));
1090+
partial_ref.len += 1;
10871091
});
1092+
partial.release_ownership();
10881093
}
10891094
}
10901095

src/zip/partial_array.rs

Lines changed: 0 additions & 144 deletions
This file was deleted.

0 commit comments

Comments
 (0)