Skip to content

Commit f4c66a6

Browse files
bors[bot]japaric
andauthored
Merge #315
315: revamp pool API r=japaric a=japaric closes #286 closes #167 closes #318 Co-authored-by: Jorge Aparicio <[email protected]>
2 parents 5229dea + 8ef085a commit f4c66a6

File tree

18 files changed

+2072
-1893
lines changed

18 files changed

+2072
-1893
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,6 @@ jobs:
250250
- x86_64-unknown-linux-gnu
251251
toolchain:
252252
- nightly
253-
features:
254-
- x86-sync-pool
255253
buildtype:
256254
- ""
257255
- "--release"

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Add `Clone` and `PartialEq` implementations to `HistoryBuffer`.
13+
- Added an object pool API. see the `pool::object` module level doc for details
1314

1415
### Changed
1516

1617
- [breaking-change] `IndexMap` and `IndexSet` now require that keys implement the `core::hash::Hash`
1718
trait instead of the `hash32::Hash` (v0.2.0) trait
19+
- move `pool::singleton::Box` to the `pool::box` module
20+
- renamed `pool::singleton::Pool` to `BoxPool` and moved it into the `pool::box` module
21+
- move `pool::singleton::arc::Arc` to the `pool::arc` module
22+
- renamed `pool::singleton::arc::Pool` to `ArcPool` and moved it into the `pool::arc` module
23+
- [breaking-change] changed the target support of memory pool API to only support 32-bit x86 and a
24+
subset of ARM targets. See the module level documentation of the `pool` module for details
1825

1926
- [breaking-change] this crate now depends on `atomic-polyfill` v1.0.1, meaning that targets that
2027
require a polyfill need a `critical-section` **v1.x.x** implementation.
@@ -26,6 +33,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2633
- [breaking-change] this crate no longer has a Minimum Supported Rust Version (MSRV) guarantee and
2734
should be used with the latest stable version of the Rust toolchain.
2835

36+
- [breaking-change] removed the `Init` and `Uninint` type states from `pool::singleton::Box`
37+
- [breaking-change] removed the following `pool::singleton::Box` methods: `freeze`, `forget` and `init`
38+
- [breaking-change] removed the `pool::singleton::arc::ArcInner` type
39+
- [breaking-change] removed support for attributes from `pool!` and `arc_pool!`
40+
2941
## [v0.7.16] - 2022-08-09
3042

3143
### Added

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ version = "0.8.0"
1818
default = ["cas"]
1919
cas = ["atomic-polyfill"]
2020
ufmt-impl = ["ufmt-write"]
21-
# read the docs before enabling: makes `Pool` Sync on x86_64
22-
x86-sync-pool = []
2321
# only for tests
2422
__trybuild = []
2523
# Enable larger MPMC sizes.

build.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#![deny(warnings)]
22

3-
use std::{env, error::Error};
3+
use std::{
4+
env,
5+
error::Error,
6+
fs,
7+
path::Path,
8+
process::{Command, ExitStatus, Stdio},
9+
};
410

511
use rustc_version::Channel;
612

@@ -89,5 +95,63 @@ fn main() -> Result<(), Box<dyn Error>> {
8995
println!("cargo:rustc-cfg=unstable_channel");
9096
}
9197

98+
match compile_probe(ARM_LLSC_PROBE) {
99+
Some(status) if status.success() => println!("cargo:rustc-cfg=arm_llsc"),
100+
_ => {}
101+
}
102+
92103
Ok(())
93104
}
105+
106+
const ARM_LLSC_PROBE: &str = r#"
107+
#![no_std]
108+
109+
// `no_mangle` forces codegen, which makes llvm check the contents of the `asm!` macro
110+
#[no_mangle]
111+
unsafe fn asm() {
112+
core::arch::asm!("clrex");
113+
}
114+
"#;
115+
116+
// this function was taken from anyhow v1.0.63 build script
117+
// https://crates.io/crates/anyhow/1.0.63 (last visited 2022-09-02)
118+
// the code is licensed under 'MIT or APACHE-2.0'
119+
fn compile_probe(source: &str) -> Option<ExitStatus> {
120+
let rustc = env::var_os("RUSTC")?;
121+
let out_dir = env::var_os("OUT_DIR")?;
122+
let probefile = Path::new(&out_dir).join("probe.rs");
123+
fs::write(&probefile, source).ok()?;
124+
125+
// Make sure to pick up Cargo rustc configuration.
126+
let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
127+
let mut cmd = Command::new(wrapper);
128+
// The wrapper's first argument is supposed to be the path to rustc.
129+
cmd.arg(rustc);
130+
cmd
131+
} else {
132+
Command::new(rustc)
133+
};
134+
135+
cmd.stderr(Stdio::null())
136+
.arg("--edition=2018")
137+
.arg("--crate-name=probe")
138+
.arg("--crate-type=lib")
139+
.arg("--out-dir")
140+
.arg(out_dir)
141+
.arg(probefile);
142+
143+
if let Some(target) = env::var_os("TARGET") {
144+
cmd.arg("--target").arg(target);
145+
}
146+
147+
// If Cargo wants to set RUSTFLAGS, use that.
148+
if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") {
149+
if !rustflags.is_empty() {
150+
for arg in rustflags.split('\x1f') {
151+
cmd.arg(arg);
152+
}
153+
}
154+
}
155+
156+
cmd.status().ok()
157+
}

src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,15 @@
4343
//!
4444
//! List of currently implemented data structures:
4545
//!
46-
//! - [`Arc`](pool/singleton/arc/struct.Arc.html) -- Thread-safe reference-counting pointer backed by a memory pool
46+
//! - [`Arc`](pool/arc/index.html) -- like `std::sync::Arc` but backed by a lock-free memory pool
47+
//! rather than `#[global_allocator]`
48+
//! - [`Box`](pool/boxed/index.html) -- like `std::boxed::Box` but backed by a lock-free memory pool
49+
//! rather than `#[global_allocator]`
4750
//! - [`BinaryHeap`](binary_heap/struct.BinaryHeap.html) -- priority queue
4851
//! - [`IndexMap`](struct.IndexMap.html) -- hash table
4952
//! - [`IndexSet`](struct.IndexSet.html) -- hash set
5053
//! - [`LinearMap`](struct.LinearMap.html)
51-
//! - [`Pool`](pool/struct.Pool.html) -- lock-free memory pool
54+
//! - [`Object`](pool/object/index.html) -- objects managed by an object pool
5255
//! - [`String`](struct.String.html)
5356
//! - [`Vec`](struct.Vec.html)
5457
//! - [`mpmc::Q*`](mpmc/index.html) -- multiple producer multiple consumer lock-free queue
@@ -75,16 +78,13 @@
7578
#![deny(rust_2018_compatibility)]
7679
#![deny(rust_2018_idioms)]
7780
#![deny(warnings)]
78-
#![deny(const_err)]
7981

8082
pub use binary_heap::BinaryHeap;
8183
pub use deque::Deque;
8284
pub use histbuf::{HistoryBuffer, OldestOrdered};
8385
pub use indexmap::{Bucket, Entry, FnvIndexMap, IndexMap, OccupiedEntry, Pos, VacantEntry};
8486
pub use indexset::{FnvIndexSet, IndexSet};
8587
pub use linear_map::LinearMap;
86-
#[cfg(all(has_cas, feature = "cas"))]
87-
pub use pool::singleton::arc::Arc;
8888
pub use string::String;
8989
pub use vec::Vec;
9090

@@ -110,7 +110,7 @@ pub mod binary_heap;
110110
mod defmt;
111111
#[cfg(all(has_cas, feature = "cas"))]
112112
pub mod mpmc;
113-
#[cfg(all(has_cas, feature = "cas"))]
113+
#[cfg(any(arm_llsc, target_arch = "x86"))]
114114
pub mod pool;
115115
pub mod sorted_linked_list;
116116
#[cfg(has_atomics)]

src/pool.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//! Memory and object pools
2+
//!
3+
//! # Target support
4+
//!
5+
//! This module / API is only available on these compilation targets:
6+
//!
7+
//! - ARM architectures which instruction set include the LDREX, CLREX and STREX instructions, e.g.
8+
//! `thumbv7m-none-eabi` but not `thumbv6m-none-eabi`
9+
//! - 32-bit x86, e.g. `i686-unknown-linux-gnu`
10+
//!
11+
//! # Benchmarks
12+
//!
13+
//! - compilation settings
14+
//! - `codegen-units = 1`
15+
//! - `lto = 'fat'`
16+
//! - `opt-level = 'z'`
17+
//! - compilation target: `thumbv7em-none-eabihf`
18+
//! - CPU: ARM Cortex-M4F
19+
//!
20+
//! - test program:
21+
//!
22+
//! ``` no_run
23+
//! use heapless::box_pool;
24+
//!
25+
//! box_pool!(P: ()); // or `arc_pool!` or `object_pool!`
26+
//!
27+
//! bkpt();
28+
//! let res = P.alloc(());
29+
//! bkpt();
30+
//!
31+
//! if let Ok(boxed) = res {
32+
//! bkpt();
33+
//! drop(boxed);
34+
//! bkpt();
35+
//! }
36+
//! # fn bkpt() {}
37+
//! ```
38+
//!
39+
//! - measurement method: the cycle counter (CYCCNT) register was sampled each time a breakpoint
40+
//! (`bkpt`) was hit. the difference between the "after" and the "before" value of CYCCNT yields the
41+
//! execution time in clock cycles.
42+
//!
43+
//! | API | clock cycles |
44+
//! |------------------------------|--------------|
45+
//! | `BoxPool::alloc` | 23 |
46+
//! | `pool::boxed::Box::drop` | 23 |
47+
//! | `ArcPool::alloc` | 28 |
48+
//! | `pool::arc::Arc::drop` | 59 |
49+
//! | `ObjectPool::request` | 23 |
50+
//! | `pool::object::Object::drop` | 23 |
51+
//!
52+
//! Note that the execution time won't include `T`'s initialization nor `T`'s destructor which will
53+
//! be present in the general case for `Box` and `Arc`.
54+
55+
mod treiber;
56+
57+
pub mod arc;
58+
pub mod boxed;
59+
pub mod object;

0 commit comments

Comments
 (0)