Skip to content

Commit c3ff5ae

Browse files
committed
fix memory leak with empty iter
1 parent a8acc13 commit c3ff5ae

File tree

2 files changed

+56
-24
lines changed

2 files changed

+56
-24
lines changed

src/concurrent_pinned_vec/into_iter_ptr_slices.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,7 @@ where
2626
G: GrowthWithConstantTimeAccess,
2727
{
2828
fn drop(&mut self) {
29-
for f in 0..self.fragments.len() {
30-
let ptr = unsafe { *self.fragments[f].get() };
31-
match ptr.is_null() {
32-
true => break,
33-
false => {
34-
let capacity = self.capacity_of(f);
35-
let _fragment_to_drop = unsafe { fragment_from_raw(ptr, 0, capacity) };
36-
}
37-
}
38-
}
29+
Self::drop_fragments(&self.growth, &mut self.fragments);
3930
}
4031
}
4132

@@ -77,7 +68,7 @@ where
7768

7869
pub fn new(
7970
capacity: usize,
80-
fragments: Vec<UnsafeCell<*mut T>>,
71+
mut fragments: Vec<UnsafeCell<*mut T>>,
8172
growth: G,
8273
range: Range<usize>,
8374
) -> Self {
@@ -87,7 +78,10 @@ where
8778
let b = min(capacity, range_end(&range, capacity));
8879

8980
match b.saturating_sub(a) {
90-
0 => Self::empty(),
81+
0 => {
82+
Self::drop_fragments(&growth, &mut fragments);
83+
Self::empty()
84+
}
9185
_ => {
9286
let (sf, si) = fragment_and_inner_indices(a);
9387
let (ef, ei) = fragment_and_inner_indices(b - 1);
@@ -112,6 +106,19 @@ where
112106
}
113107
}
114108

109+
fn drop_fragments(growth: &G, fragments: &mut Vec<UnsafeCell<*mut T>>) {
110+
for f in 0..fragments.len() {
111+
let ptr = unsafe { *fragments[f].get() };
112+
match ptr.is_null() {
113+
true => continue,
114+
false => {
115+
let capacity = growth.fragment_capacity_of(f);
116+
let _fragment_to_drop = unsafe { fragment_from_raw(ptr, 0, capacity) };
117+
}
118+
}
119+
}
120+
}
121+
115122
#[inline(always)]
116123
fn remaining_len(&self) -> usize {
117124
(1 + self.ef).saturating_sub(self.f)

src/concurrent_pinned_vec/tests/into_iter.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,49 @@ use orx_pinned_vec::{ConcurrentPinnedVec, IntoConcurrentPinnedVec, PinnedVec};
66
use std::string::{String, ToString};
77
use test_case::test_matrix;
88

9-
fn vec_doubling() -> SplitVec<String, Doubling> {
10-
(0..20).map(|x| x.to_string()).collect()
9+
fn vec_doubling(n: usize) -> SplitVec<String, Doubling> {
10+
(0..n).map(|x| x.to_string()).collect()
1111
}
1212

13-
fn vec_linear() -> SplitVec<String, Linear> {
13+
fn vec_linear(n: usize) -> SplitVec<String, Linear> {
1414
let mut vec = SplitVec::with_linear_growth(2);
15-
vec.extend((0..20).map(|x| x.to_string()));
15+
vec.extend((0..n).map(|x| x.to_string()));
1616
vec
1717
}
1818

19+
#[test_matrix([vec_doubling, vec_linear])]
20+
fn into_iter_empty<G, F>(vec: F)
21+
where
22+
G: GrowthWithConstantTimeAccess,
23+
F: Fn(usize) -> SplitVec<String, G>,
24+
{
25+
let iter = || {
26+
let vec = vec(0);
27+
let range = 0..vec.len();
28+
let convec = vec.into_concurrent();
29+
let (growth, data, capacity) = convec.destruct();
30+
ConcurrentSplitVecIntoIter::new(capacity, data, growth, range)
31+
};
32+
33+
let consume_all = iter().count();
34+
assert_eq!(consume_all, 0);
35+
36+
let mut consume_half = iter();
37+
for _ in 0..10 {
38+
_ = consume_half.next();
39+
}
40+
41+
let _consume_none = iter();
42+
}
43+
1944
#[test_matrix([vec_doubling, vec_linear])]
2045
fn into_iter_non_taken<G, F>(vec: F)
2146
where
2247
G: GrowthWithConstantTimeAccess,
23-
F: Fn() -> SplitVec<String, G>,
48+
F: Fn(usize) -> SplitVec<String, G>,
2449
{
2550
let iter = || {
26-
let vec = vec();
51+
let vec = vec(20);
2752
let range = 0..vec.len();
2853
let convec = vec.into_concurrent();
2954
let (growth, data, capacity) = convec.destruct();
@@ -45,10 +70,10 @@ where
4570
fn into_iter_taken_from_beg<G, F>(vec: F)
4671
where
4772
G: GrowthWithConstantTimeAccess,
48-
F: Fn() -> SplitVec<String, G>,
73+
F: Fn(usize) -> SplitVec<String, G>,
4974
{
5075
let iter = || {
51-
let vec = vec();
76+
let vec = vec(20);
5277
let range = 5..vec.len();
5378
let convec = vec.into_concurrent();
5479

@@ -76,10 +101,10 @@ where
76101
fn into_iter_taken_from_end<G, F>(vec: F)
77102
where
78103
G: GrowthWithConstantTimeAccess,
79-
F: Fn() -> SplitVec<String, G>,
104+
F: Fn(usize) -> SplitVec<String, G>,
80105
{
81106
let iter = || {
82-
let vec = vec();
107+
let vec = vec(20);
83108
let vec_len = vec.len();
84109
let range = 0..15;
85110
let convec = vec.into_concurrent();
@@ -108,10 +133,10 @@ where
108133
fn into_iter_taken_from_both_ends<G, F>(vec: F)
109134
where
110135
G: GrowthWithConstantTimeAccess,
111-
F: Fn() -> SplitVec<String, G>,
136+
F: Fn(usize) -> SplitVec<String, G>,
112137
{
113138
let iter = || {
114-
let vec = vec();
139+
let vec = vec(20);
115140
let vec_len = vec.len();
116141
let range = 4..15;
117142
let convec = vec.into_concurrent();

0 commit comments

Comments
 (0)