Skip to content

Commit 1b41bba

Browse files
committed
small changes and cleanup, add test binary, complete shrink_to_zero test
1 parent 493cac5 commit 1b41bba

9 files changed

Lines changed: 199 additions & 58 deletions

File tree

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
matrix:
2222
os: [ ubuntu-latest, windows-latest, macos-latest ]
2323
rust: [ stable, nightly, 1.46.0, 1.47.0, 1.49.0, 1.50.0, 1.52.0, 1.56.0, 1.57.0, 1.58.0, 1.61.0, 1.64.0, 1.71.0, 1.73.0, 1.75.0, 1.81.0, 1.83.0, 1.89.0 ]
24+
# TODO: make it work on these versions
2425
exclude:
2526
- os: macos-latest
2627
rust: 1.46.0
@@ -104,8 +105,7 @@ jobs:
104105
run: cargo +${{ matrix.rust }} miri test --verbose --features "${{ matrix.features }}"
105106

106107
- name: Run Clippy
107-
# other rust versions had weird clippy things, might check and try to fix them someday if
108-
# they are real issues
108+
# other rust versions had weird clippy things
109109
if: matrix.rust == 'nightly' || matrix.rust == 'stable'
110110
continue-on-error: false
111111
run: cargo +${{ matrix.rust }} clippy --features "${{ matrix.features }}" -- -D unused_unsafe -D warnings

Cargo.toml

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,11 @@ include = [
1919
]
2020
build = "build.rs"
2121

22-
23-
24-
[package.metadata.docs.rs]
25-
features = ["full"]
26-
27-
[badges]
28-
docsrs = { status = "passing" }
29-
maintenance = { status = "actively-developed" }
30-
31-
32-
3322
[features]
3423
default = []
3524

3625
# internal features for testing
3726
__dev = []
38-
3927
# nightly support
4028
## allows disabling allocator_api on nightly
4129
no_nightly = []
@@ -67,6 +55,39 @@ full_nightly = ["metadata", "full"]
6755

6856

6957

58+
[package.metadata.docs.rs]
59+
features = ["full"]
60+
61+
[badges]
62+
docsrs = { status = "passing" }
63+
maintenance = { status = "actively-developed" }
64+
65+
[[test]]
66+
name = "alc"
67+
path = "tests/alloc.rs"
68+
69+
[[test]]
70+
name = "malc"
71+
path = "tests/alloc_mut.rs"
72+
required-features = []
73+
74+
[[test]]
75+
name = "stk"
76+
path = "tests/stack_alloc.rs"
77+
required-features = ["stack_alloc"]
78+
79+
[[test]]
80+
name = "c_alc"
81+
path = "tests/c_alloc.rs"
82+
83+
[[test]]
84+
name = "hlp"
85+
path = "tests/helpers.rs"
86+
87+
[[test]]
88+
name = "lyt"
89+
path = "tests/layout.rs"
90+
7091
[dependencies]
7192
bitflags = "=1.3.2"
7293
libc = { version = "=0.2.163", default-features = false }
@@ -79,6 +100,12 @@ rustversion = "=1.0.22"
79100

80101

81102

103+
#[[bin]]
104+
#name = "alcm"
105+
#path = "bin/alloc_many.rs"
106+
107+
108+
82109
#[dev-dependencies]
83110
#criterion = "0.8.1"
84111
#
@@ -96,31 +123,3 @@ rustversion = "=1.0.22"
96123
#name = "hlp"
97124
#path = "benches/helpers.rs"
98125
#harness = false
99-
100-
101-
102-
[[test]]
103-
name = "alc"
104-
path = "tests/alloc.rs"
105-
106-
[[test]]
107-
name = "malc"
108-
path = "tests/alloc_mut.rs"
109-
required-features = []
110-
111-
[[test]]
112-
name = "stk"
113-
path = "tests/stack_alloc.rs"
114-
required-features = ["stack_alloc"]
115-
116-
[[test]]
117-
name = "c_alc"
118-
path = "tests/c_alloc.rs"
119-
120-
[[test]]
121-
name = "hlp"
122-
path = "tests/helpers.rs"
123-
124-
[[test]]
125-
name = "lyt"
126-
path = "tests/layout.rs"

bench.sh

100644100755
File mode changed.

bin/alloc_many.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use {
2+
memapi2::{helpers::ptr_max_align, prelude::*},
3+
std::{
4+
env,
5+
error::Error,
6+
io::{BufRead, Write, stdin, stdout}
7+
}
8+
};
9+
10+
fn main() {
11+
let o = stdout();
12+
let i = stdin();
13+
14+
let mut out = o.lock();
15+
let mut inp = i.lock();
16+
17+
let auto = env::args().any(|a| a == "--auto" || a == "-a");
18+
19+
let a = DefaultAlloc;
20+
21+
let mut total_sizes_tried: u128 = 0;
22+
let mut total_alloc_attempts: u128 = 0;
23+
let mut total_successes: u128 = 0;
24+
let mut total_failures: u128 = 0;
25+
let mut total_bytes_allocated: u128 = 0;
26+
let mut max_success_size: usize = 0;
27+
let mut max_success_align: usize = 0;
28+
let mut max_success_size_align: usize = 0;
29+
let mut max_align_attempted: usize = 0;
30+
31+
let mut size = 1;
32+
let mut align = 1;
33+
loop {
34+
total_sizes_tried += 1;
35+
36+
let err: Box<dyn Error> = loop {
37+
if !auto {
38+
inp.read_line(&mut String::new()).unwrap();
39+
write!(out, "\x1b[1A\x1b[2K").unwrap();
40+
out.flush().unwrap();
41+
}
42+
43+
// Track an allocation attempt for this size/align pair
44+
total_alloc_attempts += 1;
45+
if align > max_align_attempted {
46+
max_align_attempted = align;
47+
}
48+
49+
let layout = match Layout::from_size_align(size, align) {
50+
Ok(layout) => layout,
51+
Err(e) => {
52+
total_failures += 1;
53+
break Box::new(e)
54+
}
55+
};
56+
57+
write!(out, "created Layout(size={}, align={})", layout.size(), layout.align())
58+
.unwrap();
59+
60+
let ptr = a.alloc(layout);
61+
match ptr {
62+
Ok(ptr) => {
63+
total_successes += 1;
64+
total_bytes_allocated += layout.size() as u128;
65+
if layout.size() > max_success_size {
66+
max_success_size = layout.size();
67+
max_success_size_align = layout.align();
68+
}
69+
if layout.align() > max_success_align {
70+
max_success_align = layout.align();
71+
}
72+
73+
write!(out, "; allocated ptr={:p}", ptr).unwrap();
74+
write!(out, "; aligned_to={}", ptr_max_align(ptr)).unwrap();
75+
writeln!(out).unwrap();
76+
out.flush().unwrap();
77+
78+
unsafe {
79+
a.dealloc(ptr, layout);
80+
}
81+
}
82+
Err(e) => {
83+
total_failures += 1;
84+
break Box::new(e)
85+
}
86+
}
87+
88+
align *= 2
89+
};
90+
91+
writeln!(out, "Layout({}, {}) failed with error: {}\n", size, align, err).unwrap();
92+
if align == 1 {
93+
// we failed on the first attempt, size is too large.
94+
break;
95+
}
96+
align = 1;
97+
size += 1;
98+
}
99+
100+
// Final summary
101+
let success_rate = if total_alloc_attempts == 0 {
102+
0.0
103+
} else {
104+
(total_successes as f64) / (total_alloc_attempts as f64) * 100.0
105+
};
106+
107+
writeln!(out, "=== Final stats ===").unwrap();
108+
writeln!(out, "sizes tried: {}", total_sizes_tried).unwrap();
109+
writeln!(out, "allocation attempts: {}", total_alloc_attempts).unwrap();
110+
writeln!(out, "successes: {}", total_successes).unwrap();
111+
writeln!(out, "failures: {}", total_failures).unwrap();
112+
writeln!(out, "success rate: {:.2}%", success_rate).unwrap();
113+
writeln!(out, "total bytes allocated (sum of successful sizes): {}", total_bytes_allocated).unwrap();
114+
writeln!(out, "largest successful size: {}", max_success_size).unwrap();
115+
writeln!(out, "largest successful size's largest align: {}", max_success_size_align).unwrap();
116+
writeln!(out, "largest successful alignment: {}", max_success_align).unwrap();
117+
writeln!(out, "largest alignment attempted: {}", max_align_attempted).unwrap();
118+
writeln!(out, "====================").unwrap();
119+
}

src/error.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ pub enum Error {
3434
/// The layout with the provided size and alignment is invalid; see the contained reason.
3535
LayoutError(LayoutErr),
3636
/// Attempted to grow to a smaller size.
37+
///
38+
/// The first contained value is the original size, while the second is the new size.
3739
GrowSmallerNewLayout(usize, usize),
3840
/// Attempted to shrink to a larger size.
41+
///
42+
/// The first contained value is the original size, while the second is the new size.
3943
ShrinkLargerNewLayout(usize, usize),
4044
/// Attempted to reallocate a block with a smaller alignment.
45+
///
46+
/// The first contained value is the original alignment, while the second is the new alignment.
4147
ReallocSmallerAlign(usize, usize),
4248
/// An arithmetic error.
4349
ArithmeticError(ArithErr),
@@ -66,7 +72,7 @@ impl Display for Error {
6672
match self {
6773
AllocFailed(l, c) => write!(
6874
f,
69-
"allocation failed: Layout(size: {}, align: {}), cause: {}",
75+
"allocation failed: Layout(size: {}, align: {}), {}",
7076
l.size(),
7177
l.align(),
7278
c
@@ -118,7 +124,7 @@ pub enum Cause {
118124
impl Display for Cause {
119125
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
120126
match self {
121-
Cause::Unknown => write!(f, "unknown"),
127+
Cause::Unknown => write!(f, "cause: unknown"),
122128
Cause::OutOfMemory => write!(f, "out of memory"),
123129
Cause::Other(other) => write!(f, "{}", other),
124130
#[cfg(not(feature = "os_err_reporting"))]
@@ -142,7 +148,7 @@ pub enum LayoutErr {
142148
/// The alignment was not a power of two. Instead, it was the contained value.
143149
NonPowerOfTwoAlign(usize),
144150
/// The total size of an array, when rounded up to the nearest multiple of its item's alignment,
145-
/// would exceed [`USIZE_MAX_NO_HIGH_BIT`](crate::helpers::USIZE_MAX_NO_HIGH_BIT).
151+
/// would exceed [`USIZE_MAX_NO_HIGH_BIT`].
146152
///
147153
/// The first contained value is the size of the elements, the second is the alignment of the
148154
/// element type, and the third is the number of elements.

src/traits/alloc_checked.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,8 @@ pub mod alloc_mut {
381381
/// supported.
382382
/// - <code>Err([Error::Other]\(err\))</code> for allocator-specific validation failures. If
383383
/// the `alloc_mut` feature is enabled, and using this method on a synchronization
384-
/// primitive wrapping a type which implements
385-
/// [`GrowMut`](crate::traits::alloc_mut::GrowMut), a generic error message will also be
386-
/// returned if locking the primitive fails.
384+
/// primitive wrapping a type which implements [`GrowMut`], a generic error message will
385+
/// also be returned if locking the primitive fails.
387386
fn checked_grow_mut(
388387
&mut self,
389388
ptr: NonNull<u8>,
@@ -409,9 +408,8 @@ pub mod alloc_mut {
409408
/// supported.
410409
/// - <code>Err([Error::Other]\(err\))</code> for allocator-specific validation failures. If
411410
/// the `alloc_mut` feature is enabled, and using this method on a synchronization
412-
/// primitive wrapping a type which implements
413-
/// [`GrowMut`](crate::traits::alloc_mut::GrowMut), a generic error message will also be
414-
/// returned if locking the primitive fails.
411+
/// primitive wrapping a type which implements [`GrowMut`], a generic error message will
412+
/// also be returned if locking the primitive fails.
415413
fn checked_zgrow_mut(
416414
&mut self,
417415
ptr: NonNull<u8>,
@@ -442,9 +440,8 @@ pub mod alloc_mut {
442440
/// - <code>Err([Error::Unsupported])</code> if checked reallocation is unsupported.
443441
/// - <code>Err([Error::Other]\(err\))</code> for allocator-specific validation failures. If
444442
/// the `alloc_mut` feature is enabled, and using this method on a synchronization
445-
/// primitive wrapping a type which implements
446-
/// [`ReallocMut`](crate::traits::alloc_mut::ReallocMut), a generic error message will
447-
/// also be returned if locking the primitive fails.
443+
/// primitive wrapping a type which implements [`ReallocMut`], a generic error message
444+
/// will also be returned if locking the primitive fails.
448445
fn checked_realloc_mut(
449446
&mut self,
450447
ptr: NonNull<u8>,
@@ -472,9 +469,8 @@ pub mod alloc_mut {
472469
/// - <code>Err([Error::Unsupported])</code> if checked reallocation is unsupported.
473470
/// - <code>Err([Error::Other]\(err\))</code> for allocator-specific validation failures. If
474471
/// the `alloc_mut` feature is enabled, and using this method on a synchronization
475-
/// primitive wrapping a type which implements
476-
/// [`ReallocMut`](crate::traits::alloc_mut::ReallocMut), a generic error message will
477-
/// also be returned if locking the primitive fails.
472+
/// primitive wrapping a type which implements [`ReallocMut`], a generic error message
473+
/// will also be returned if locking the primitive fails.
478474
fn checked_rezalloc_mut(
479475
&mut self,
480476
ptr: NonNull<u8>,

test.sh

100644100755
File mode changed.

tests/alloc.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,15 @@ fn test_shrink_and_error_cases() {
7373

7474
#[test]
7575
fn shrink_to_zero() {
76-
todo!()
76+
let allocator = DefaultAlloc;
77+
78+
let old = Layout::from_size_align(8, 2).unwrap();
79+
let new = Layout::from_size_align(0, 2).unwrap();
80+
81+
let ptr = allocator.alloc(old).unwrap();
82+
let new = unsafe {allocator.shrink(ptr, old, new)}.unwrap();
83+
84+
assert_eq!(new.as_ptr() as usize, 2);
7785
}
7886

7987
#[test]

tests/c_alloc.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@ fn test_shrink_and_error_cases() {
7575
}
7676
}
7777

78+
#[test]
79+
fn shrink_to_zero() {
80+
let allocator = CAlloc;
81+
82+
let old = Layout::from_size_align(8, 2).unwrap();
83+
let new = Layout::from_size_align(0, 2).unwrap();
84+
85+
let ptr = allocator.alloc(old).unwrap();
86+
let new = unsafe {allocator.shrink(ptr, old, new)}.unwrap();
87+
88+
assert_eq!(new.as_ptr() as usize, 2);
89+
}
90+
7891
#[test]
7992
fn grow_preserves_prefix() {
8093
let a = CAlloc;

0 commit comments

Comments
 (0)