diff --git a/examples/a-chat/server.rs b/examples/a-chat/server.rs index e049a490e..e580fa5fc 100644 --- a/examples/a-chat/server.rs +++ b/examples/a-chat/server.rs @@ -10,6 +10,7 @@ use async_std::{ net::{TcpListener, TcpStream, ToSocketAddrs}, prelude::*, task, + task::RuntimeConfig, }; type Result = std::result::Result>; @@ -20,6 +21,11 @@ type Receiver = mpsc::UnboundedReceiver; enum Void {} pub(crate) fn main() -> Result<()> { + let mut config = RuntimeConfig::new(); + let num_threads = num_cpus::get() / 2; + config.num_thread(num_threads).thread_name("a-chat-server"); + assert!(config.finalize().is_ok()); + task::block_on(accept_loop("127.0.0.1:8080")) } diff --git a/src/task/executor/mod.rs b/src/task/executor/mod.rs index 2a6a696e1..af760a526 100644 --- a/src/task/executor/mod.rs +++ b/src/task/executor/mod.rs @@ -6,6 +6,7 @@ //! * The only import is the `crate::task::Runnable` type. pub(crate) use pool::schedule; +pub use pool::RuntimeConfig; use sleepers::Sleepers; diff --git a/src/task/executor/pool.rs b/src/task/executor/pool.rs index 5249b3d93..d4284366a 100644 --- a/src/task/executor/pool.rs +++ b/src/task/executor/pool.rs @@ -11,6 +11,50 @@ use crate::task::executor::Sleepers; use crate::task::Runnable; use crate::utils::{abort_on_panic, random}; +type SyncOnceCell = once_cell::sync::OnceCell; +static RUNTIME_CONFIG: SyncOnceCell = SyncOnceCell::new(); + +/// configuration parameters for executor +#[derive(Debug)] +pub struct RuntimeConfig { + /// Name given to created worker threads + pub thread_name: String, + + /// Number of threads executor is allowed to create + pub num_threads: usize, +} +impl Default for RuntimeConfig { + fn default() -> Self { + Self { + thread_name: "async-std/executor".to_string(), + num_threads: num_cpus::get(), + } + } +} +impl RuntimeConfig { + /// Creates new config with predefined defaults + pub fn new() -> RuntimeConfig { + RuntimeConfig::default() + } + + /// Configures name given to worker threads + pub fn thread_name(&mut self, thread_name: impl Into) -> &mut Self { + self.thread_name = thread_name.into(); + self + } + + /// Configures number of worker threads + pub fn num_thread(&mut self, num_threads: usize) -> &mut Self { + self.num_threads = num_threads; + self + } + + /// Sets `RUNTIME_CONFIG` with self + pub fn finalize(self) -> Result<(), RuntimeConfig> { + RUNTIME_CONFIG.set(self) + } +} + /// The state of an executor. struct Pool { /// The global queue of tasks. @@ -25,7 +69,8 @@ struct Pool { /// Global executor that runs spawned tasks. static POOL: Lazy = Lazy::new(|| { - let num_threads = num_cpus::get().max(1); + let runtime_config = RUNTIME_CONFIG.get_or_init(|| RuntimeConfig::default()); + let num_threads = runtime_config.num_threads.max(1); let mut stealers = Vec::new(); // Spawn worker threads. @@ -40,7 +85,7 @@ static POOL: Lazy = Lazy::new(|| { }; thread::Builder::new() - .name("async-std/executor".to_string()) + .name(runtime_config.thread_name.clone()) .spawn(|| { let _ = PROCESSOR.with(|p| p.set(proc)); abort_on_panic(main_loop); diff --git a/src/task/mod.rs b/src/task/mod.rs index 13fe9032d..a172c5881 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -140,6 +140,7 @@ cfg_default! { pub use sleep::sleep; pub use spawn::spawn; pub use task_local::{AccessError, LocalKey}; + pub use executor::RuntimeConfig; use builder::Runnable; use task_local::LocalsMap;