1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
// License: see LICENSE file at root directory of `master` branch //! # Blackhole //! //! _...to throw your threads into._ //! //! ## Project //! //! - Repository: <https://bitbucket.org/haibison/blackhole-rs> //! - License: [Free Public License 1.0.0](https://opensource.org/licenses/FPL-1.0.0) //! - _This project follows [Semantic Versioning 2.0.0]_ //! //! ## Features //! //! Simple thread manager. //! //! ## Design //! //! It uses a [channel][std::sync::mpsc] and one job manager thread: //! //! - When you throw a new job, it checks for active job count. //! //! + If that count is smaller than limit, it spawns a new runner thread to run that job. //! + If that count is equal to limit: //! //! * If job queue is smaller than limit, it pushes the job into the queue. //! * Otherwise the job is discarded. An error message is printed to stderr. And the job is returned to you for recovery. //! //! - When the runner thread finishes the first job, it contacts job manager to ask for new jobs to run. If there are no new jobs, it finishes //! itself and notifies job manager about that. //! - When job manager receives job-finished-message, it checks job queue to spawn new runner threads, if necessary. //! //! ## Examples //! //! ``` //! use blackhole::{ActiveLimit, Blackhole, Job}; //! //! /// # This job takes a `usize`, if it's odd, sends it to Printer //! struct Handler { //! data: usize, //! } //! //! impl Job for Handler { //! //! fn run(&mut self) -> Option<Box<Job>> { //! match self.data % 2 { //! 0 => None, //! _ => Some(Box::new(Printer { data: self.data })), //! } //! } //! //! } //! //! /// # This job prints data and does nothing else //! struct Printer { //! data: usize, //! } //! //! impl Job for Printer { //! //! fn run(&mut self) -> Option<Box<Job>> { //! println!("{}", self.data); //! None //! } //! //! } //! //! let active_limit = ActiveLimit::new(4); //! let queue_limit: usize = 10; //! let blackhole = Blackhole::make(active_limit, queue_limit).unwrap(); //! for i in 0 .. queue_limit * 2 { //! match blackhole.throw(Handler { data: i }) { //! Ok(None) => println!("Job is accepted"), //! // If job is discarded, it will be sent back here. //! Ok(Some(job)) => { //! eprintln!("Job is discarded! We'll run it ourselves!"); //! blackhole::run_to_end(job); //! }, //! Err(err) => { //! eprintln!("Blackhole is... exploded: {}", err); //! break; //! }, //! }; //! } //! blackhole.escape_on_idle().unwrap(); //! ``` //! //! [Semantic Versioning 2.0.0]: https://semver.org/spec/v2.0.0.html //! [std::sync::mpsc]: https://doc.rust-lang.org/std/sync/mpsc/index.html #![warn(missing_docs)] #[macro_use] #[allow(unused_macros)] mod __; mod job; mod root; pub use job::*; pub use root::*; pub mod version_info; // ╔═════════════════╗ // ║ IDENTIFIERS ║ // ╚═════════════════╝ macro_rules! code_name { () => { "blackhole" }} macro_rules! version { () => { "0.11.0" }} /// # Crate name pub const NAME: &'static str = "Blackhole"; /// # Crate code name pub const CODE_NAME: &'static str = code_name!(); /// # Crate version pub const VERSION: &'static str = version!(); /// # Crate release date (year/month/day) pub const RELEASE_DATE: (u16, u8, u8) = (2019, 3, 15); /// # Unique universally identifier of this crate pub const UUID: &'static str = "f611f491-608a-44a1-8831-594a58c4c202"; /// # Tag, which can be used for logging... pub const TAG: &'static str = concat!(code_name!(), "::f611f491::", version!()); // ╔════════════════════╗ // ║ IMPLEMENTATION ║ // ╚════════════════════╝ #[test] fn test_crate_version() { assert_eq!(VERSION, env!("CARGO_PKG_VERSION")); } /// # Gets online processors /// /// This ***unsafe-unstable*** macro requires `libc` crate. `$fake` is an `Option<Into<u64>>`, which will be used if calling to `libc` fails. If /// you provide `None`, `1_u8` will be used. /// /// ## Examples /// /// ``` /// let online_processors: u64 = unsafe { /// blackhole::get_online_processors!(None) /// }; /// assert!(online_processors > 0); /// ``` /// /// ## References /// /// - <https://www.gnu.org/software/libc/manual/html_node/Processor-Resources.html> #[macro_export] macro_rules! get_online_processors { ($fake: expr) => {{ let tmp: i64 = libc::sysconf(libc::_SC_NPROCESSORS_ONLN); match tmp > 0 { true => tmp as u64, false => u64::from($fake.unwrap_or(1_u8)), } }}}