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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
//! A rust library built on top of [`std::thread`](https://doc.rust-lang.org/stable/std/thread/) //! to provide additional features and tools to make development easier and to support operators. //! //! ## Spawning threads //! Threads are created with a [`Builder`] similar to [`std::thread::Builder`]. //! //! ``` //! use std::thread::sleep; //! use std::time::Duration; //! //! use humthreads::Builder; //! //!# fn main() { //! let thread = Builder::new("os-thread-name") //! .spawn(|scope| { //! // This code is run in a separate thread. //! // The `scope` attribute can be used to interact with advanced APIs. //! while !scope.should_shutdown() { //! // Do work in the background //! sleep(Duration::from_millis(10)); //! } //! }) //! .expect("failed to spawn thread"); //! //! // With a humthreads thread we can request the background thread to stop itself. //! thread.request_shutdown(); //! thread.join().expect("background thread paniced"); //!# } //! ``` //! //! ## Inspecting running threads //! One of the biggest differences from [`std::thread`] is that `humthreads` provide an API to //! fetch a list of running threads and inspect some of their properties. //! //! ``` //! use std::thread::sleep; //! use std::time::Duration; //! //! use humthreads::registered_threads; //! use humthreads::Builder; //! //!# fn main() { //! let thread1 = Builder::new("thread1") //! .spawn(|scope| { //! while !scope.should_shutdown() { //! sleep(Duration::from_millis(10)); //! } //! }) //! .expect("failed to spawn thread1"); //! let thread2 = Builder::new("thread2") //! .spawn(|scope| { //! while !scope.should_shutdown() { //! sleep(Duration::from_millis(10)); //! } //! }) //! .expect("failed to spawn thread2"); //! //! // Give threads a chance to start or we'll have nothing to inspect. //! sleep(Duration::from_millis(20)); //! //! // Fetch a snapshot of running threads and print some information. //! let threads = registered_threads(); //! for thread in threads { //! println!("Thread name: {}", thread.name); //! println!("Thread name passed to the OS: {}", thread.short_name); //! println!("Current thread activity: {:?}", thread.activity); //! } //! //! // With a humthreads thread we can request the background thread to stop itself. //! thread1.request_shutdown(); //! thread2.request_shutdown(); //! thread1.join().expect("background thread1 paniced"); //! thread2.join().expect("background thread2 paniced"); //!# } //! ``` //! //! ### Reporting threads activity //! End users of multi-threaded application often wish for a way to understand what the //! application is doing without having to read the code and study the concurrent actions. //! This is valuable insight not just in the presence of bugs but also in case of poor performance //! or simply for users that wish to know more of what is going on under the hood. //! //! Threads must themselves report what they are working on. //! What `humthreads` does is provide helpers for developers to make it easy to report //! and expose current activity for each thread: //! //! ``` //! use std::thread::sleep; //! use std::time::Duration; //! //! use humthreads::Builder; //! //!# fn main() { //! let thread = Builder::new("os-thread-name") //! .spawn(|scope| { //! // Set the current activity, overriding the current message. //! scope.activity("waiting for work"); //! //! // Simulare looping over messages. //! for task in 0..10 { //! // Change the reported activity for the duration of the scope. //! // The message is reverted to what we set above when `_activity` is dropped. //! let _activity = scope.scoped_activity(format!("processing task {}", task)); //! sleep(Duration::from_millis(10)); //! } //! }) //! .expect("failed to spawn thread"); //! thread.join().expect("background thread paniced"); //!# } //! ``` //! //! ### Waiting for threads with Select //! ``` //! use std::thread::sleep; //! use std::time::Duration; //! //! use crossbeam_channel::Select; //! //! use humthreads::Builder; //! //!# fn main() { //! let thread1 = Builder::new("thread1") //! .spawn(|_| { //! sleep(Duration::from_millis(50)); //! }) //! .expect("failed to spawn thread1"); //! let thread2 = Builder::new("thread2") //! .spawn(|_| { //! sleep(Duration::from_millis(10)); //! }) //! .expect("failed to spawn thread2"); //! //! // Wait for a thread to exit with the Select API. //! let mut set = Select::new(); //! let idx1 = thread1.select_add(&mut set); //! let idx2 = thread2.select_add(&mut set); //! let op = set.select_timeout(Duration::from_millis(20)).expect("selection to find thread2"); //! assert_eq!(idx2, op.index()); //! thread2.select_join(op).expect("thread2 to have exited successfully"); //!# } //! ``` //! //! You can also use the [`Select::ready`] API and then use [`Thread::join`] or //! [`Thread::join_timeout`] to join with the thread. //! //! [`Builder`]: struct.Builder.html //! [`Thread::join`]: struct.Thread.html#method.join //! [`Thread::join_timeout`]: struct.Thread.html#method.join_timeout //! [`std::thread`]: https://doc.rust-lang.org/stable/std/thread/index.html //! [`std::thread::Builder`]: https://doc.rust-lang.org/stable/std/thread/struct.Builder.html //! [`Select::ready`]: https://docs.rs/crossbeam-channel/0.3.8/crossbeam_channel/struct.Select.html #![doc(html_root_url = "https://docs.rs/humthreads/0.2.0")] extern crate crossbeam_channel; extern crate failure; extern crate lazy_static; extern crate serde; #[macro_use] extern crate serde_derive; mod builder; mod error; mod handles; mod registry; mod status; #[cfg(feature = "with_test_support")] pub mod test_support; pub use self::builder::Builder; pub use self::error::Error; pub use self::error::ErrorKind; pub use self::error::Result; pub use self::handles::MapThread; pub use self::handles::Thread; pub use self::handles::ThreadScope; pub use self::handles::ThreadScopeActivityGuard; pub use self::registry::registered_threads; pub use self::status::ThreadStatus;