diff --git a/Cargo.lock b/Cargo.lock index 62fa319..06be72e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,8 @@ version = "0.1.0" dependencies = [ "memmap", "num_cpus", + "rustc_version", + "smallvec", ] [[package]] @@ -43,6 +45,36 @@ dependencies = [ "libc", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "smallvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 006a1b1..54b58ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,8 @@ edition = "2018" [dependencies] memmap = "0.7.0" num_cpus = "1.13.0" +smallvec = "1.5.1" + +[build-dependencies] +rustc_version = "0.2" +num_cpus = "1.13.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..52acfcb --- /dev/null +++ b/build.rs @@ -0,0 +1,46 @@ + +extern crate rustc_version; +extern crate num_cpus; + +use rustc_version::{version, version_meta, Channel}; +use std::io::{self, Write}; +use std::fs::OpenOptions; + +pub const DEFAULT_CPU_FILE: &str = "./src/consts.rs"; + +fn write_numcpus() -> io::Result<()> +{ + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(DEFAULT_CPU_FILE)?; + + writeln!(&mut file, "pub const CPUS: usize = {};", num_cpus::get())?; + writeln!(&mut file, "pub type PoolContainer = [T; CPUS+1];")?; + file.flush()?; + Ok(()) +} + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + match version_meta().unwrap().channel { + Channel::Stable => { + println!("cargo:rustc-cfg=stable"); + } + Channel::Beta => { + println!("cargo:rustc-cfg=beta"); + } + Channel::Nightly => { + println!("cargo:rustc-cfg=nightly"); + } + Channel::Dev => { + println!("cargo:rustc-cfg=dev"); + } + } + + write_numcpus().expect("Failed to write comptime cpu info to source") +} diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..8235ec2 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,2 @@ +pub const CPUS: usize = 8; +pub type PoolContainer = [T; CPUS+1]; diff --git a/src/main.rs b/src/main.rs index 16d8915..2f363e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ mod map; mod job; mod work; +mod consts; + fn main() { println!("Hello, world!"); } diff --git a/src/pool.rs b/src/pool.rs index 07406c7..155c6b5 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -66,9 +66,15 @@ pub fn join_all(i: impl IntoIterator>) } } +/// Vector type used for thread pool waiting. +/// +/// This container is compiled will an estimate of enough stack storage for a reasonably sized thread pool. +/// The number of processors of the CPU this binary was built on is used as this estimate, and will only heap allocate when spawning more threads that number. +pub type PoolContainer = smallvec::SmallVec<[JoinHandle<()>; crate::consts::CPUS]>; + /// A pool container that ensures worker threads are waited on before termination. #[derive(Debug)] -pub struct Pool(Vec>); +pub struct Pool(PoolContainer); impl Pool { @@ -81,7 +87,7 @@ impl Pool /// Detach the pool but do not join its worker threads. #[inline] pub fn detach(mut self) { - self.0 = Vec::default(); + self.0 = Default::default(); } /// The number of threads in the pool @@ -102,11 +108,11 @@ impl FromIterator> for Pool impl IntoIterator for Pool { type Item= JoinHandle<()>; - type IntoIter = std::vec::IntoIter>; + type IntoIter = smallvec::IntoIter<[JoinHandle<()>; crate::consts::CPUS]>; fn into_iter(mut self) -> Self::IntoIter { - std::mem::replace(&mut self.0, Vec::default()).into_iter() + std::mem::replace(&mut self.0, Default::default()).into_iter() } } @@ -115,7 +121,7 @@ impl Drop for Pool fn drop(&mut self) { if self.0.len() > 0 { - join_all(std::mem::replace(&mut self.0, Vec::default())); + join_all(std::mem::replace(&mut self.0, Default::default())); } } }