@@ -5,7 +5,7 @@ use std::{
55 pin:: Pin ,
66 sync:: atomic:: { AtomicUsize , Ordering } ,
77 task:: { Context , Poll } ,
8- thread,
8+ thread, usize ,
99} ;
1010
1111use futures_core:: ready;
@@ -80,42 +80,79 @@ impl ArbiterHandle {
8080 }
8181}
8282
83- /// An Arbiter represents a thread that provides an asynchronous execution environment for futures
84- /// and functions.
85- ///
86- /// When an arbiter is created, it spawns a new [OS thread](thread), and hosts an event loop.
87- #[ derive( Debug ) ]
88- pub struct Arbiter {
89- tx : mpsc:: UnboundedSender < ArbiterCommand > ,
90- thread_handle : thread:: JoinHandle < ( ) > ,
83+ /// A builder for configuring and spawning a new [Arbiter] thread.
84+ pub struct ArbiterBuilder {
85+ name_factory : Option < Box < dyn Fn ( usize , usize ) -> String + ' static > > ,
86+ #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
87+ runtime_factory : Option < Box < dyn Fn ( ) -> tokio:: runtime:: Runtime + Send + ' static > > ,
9188}
9289
93- impl Arbiter {
94- /// Spawn a new Arbiter thread and start its event loop.
95- ///
96- /// # Panics
97- /// Panics if a [System] is not registered on the current thread.
98- #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
90+ impl ArbiterBuilder {
91+ /// Create a new [ArbiterBuilder].
9992 #[ allow( clippy:: new_without_default) ]
100- pub fn new ( ) -> Arbiter {
101- Self :: with_tokio_rt ( || {
102- crate :: runtime:: default_tokio_runtime ( ) . expect ( "Cannot create new Arbiter's Runtime." )
103- } )
93+ pub fn new ( ) -> Self {
94+ Self {
95+ name_factory : None ,
96+ #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
97+ runtime_factory : None ,
98+ }
10499 }
105100
106- /// Spawn a new Arbiter using the [Tokio Runtime](tokio-runtime) returned from a closure.
101+ /// Specify a factory function for generating the name of the Arbiter thread.
102+ ///
103+ /// Defaults to `actix-rt|system:<system_id>|arbiter:<arb_id>`
104+ ///
105+ /// # Example
106+ ///
107+ /// ```no_run
108+ /// let _ = actix_rt::System::new();
109+ /// actix_rt::ArbiterBuilder::new()
110+ /// .name(|system_id, arb_id| {
111+ /// format!("some-prefix|system:{}|arbiter:{}", system_id, arb_id)
112+ /// })
113+ /// .build();
114+ /// ```
115+ pub fn name < N > ( mut self , name_factory : N ) -> Self
116+ where
117+ N : Fn ( usize , usize ) -> String + ' static ,
118+ {
119+ self . name_factory = Some ( Box :: new ( name_factory) ) ;
120+ self
121+ }
122+
123+ /// Specify a factory function for generating the [Tokio Runtime](tokio-runtime) used by the Arbiter.
107124 ///
108125 /// [tokio-runtime]: tokio::runtime::Runtime
109126 #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
110- pub fn with_tokio_rt < F > ( runtime_factory : F ) -> Arbiter
127+ pub fn runtime < R > ( mut self , runtime_factory : R ) -> Self
111128 where
112- F : Fn ( ) -> tokio:: runtime:: Runtime + Send + ' static ,
129+ R : Fn ( ) -> tokio:: runtime:: Runtime + Send + ' static ,
113130 {
131+ self . runtime_factory = Some ( Box :: new ( runtime_factory) ) ;
132+ self
133+ }
134+
135+ /// Spawn a new Arbiter thread and start its event loop.
136+ ///
137+ /// # Panics
138+ /// Panics if a [System] is not registered on the current thread.
139+ #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
140+ pub fn build ( self ) -> Arbiter {
114141 let sys = System :: current ( ) ;
115142 let system_id = sys. id ( ) ;
116143 let arb_id = COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
117144
118- let name = format ! ( "actix-rt|system:{}|arbiter:{}" , system_id, arb_id) ;
145+ let name = self . name_factory . unwrap_or_else ( || {
146+ Box :: new ( |system_id, arb_id| {
147+ format ! ( "actix-rt|system:{}|arbiter:{}" , system_id, arb_id)
148+ } )
149+ } ) ( system_id, arb_id) ;
150+ let runtime_factory = self . runtime_factory . unwrap_or_else ( || {
151+ Box :: new ( || {
152+ crate :: runtime:: default_tokio_runtime ( )
153+ . expect ( "Cannot create new Arbiter's Runtime." )
154+ } )
155+ } ) ;
119156 let ( tx, rx) = mpsc:: unbounded_channel ( ) ;
120157
121158 let ( ready_tx, ready_rx) = std:: sync:: mpsc:: channel :: < ( ) > ( ) ;
@@ -160,13 +197,16 @@ impl Arbiter {
160197 /// # Panics
161198 /// Panics if a [System] is not registered on the current thread.
162199 #[ cfg( all( target_os = "linux" , feature = "io-uring" ) ) ]
163- #[ allow( clippy:: new_without_default) ]
164- pub fn new ( ) -> Arbiter {
200+ pub fn build ( self ) -> Arbiter {
165201 let sys = System :: current ( ) ;
166202 let system_id = sys. id ( ) ;
167203 let arb_id = COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
168204
169- let name = format ! ( "actix-rt|system:{}|arbiter:{}" , system_id, arb_id) ;
205+ let name = self . name_factory . unwrap_or_else ( || {
206+ Box :: new ( |system_id, arb_id| {
207+ format ! ( "actix-rt|system:{}|arbiter:{}" , system_id, arb_id)
208+ } )
209+ } ) ( system_id, arb_id) ;
170210 let ( tx, rx) = mpsc:: unbounded_channel ( ) ;
171211
172212 let ( ready_tx, ready_rx) = std:: sync:: mpsc:: channel :: < ( ) > ( ) ;
@@ -204,6 +244,54 @@ impl Arbiter {
204244
205245 Arbiter { tx, thread_handle }
206246 }
247+ }
248+
249+ /// An Arbiter represents a thread that provides an asynchronous execution environment for futures
250+ /// and functions.
251+ ///
252+ /// When an arbiter is created, it spawns a new [OS thread](thread), and hosts an event loop.
253+ #[ derive( Debug ) ]
254+ pub struct Arbiter {
255+ tx : mpsc:: UnboundedSender < ArbiterCommand > ,
256+ thread_handle : thread:: JoinHandle < ( ) > ,
257+ }
258+
259+ impl Arbiter {
260+ /// Create an [ArbiterBuilder] to configure and spawn a new Arbiter thread.
261+ pub fn builder ( ) -> ArbiterBuilder {
262+ ArbiterBuilder :: new ( )
263+ }
264+
265+ /// Spawn a new Arbiter thread and start its event loop.
266+ ///
267+ /// # Panics
268+ /// Panics if a [System] is not registered on the current thread.
269+ #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
270+ #[ allow( clippy:: new_without_default) ]
271+ pub fn new ( ) -> Arbiter {
272+ ArbiterBuilder :: new ( ) . build ( )
273+ }
274+
275+ /// Spawn a new Arbiter using the [Tokio Runtime](tokio-runtime) returned from a closure.
276+ ///
277+ /// [tokio-runtime]: tokio::runtime::Runtime
278+ #[ cfg( not( all( target_os = "linux" , feature = "io-uring" ) ) ) ]
279+ pub fn with_tokio_rt < F > ( runtime_factory : F ) -> Arbiter
280+ where
281+ F : Fn ( ) -> tokio:: runtime:: Runtime + Send + ' static ,
282+ {
283+ ArbiterBuilder :: new ( ) . runtime ( runtime_factory) . build ( )
284+ }
285+
286+ /// Spawn a new Arbiter thread and start its event loop with `tokio-uring` runtime.
287+ ///
288+ /// # Panics
289+ /// Panics if a [System] is not registered on the current thread.
290+ #[ cfg( all( target_os = "linux" , feature = "io-uring" ) ) ]
291+ #[ allow( clippy:: new_without_default) ]
292+ pub fn new ( ) -> Arbiter {
293+ ArbiterBuilder :: new ( ) . build ( )
294+ }
207295
208296 /// Sets up an Arbiter runner in a new System using the environment's local set.
209297 pub ( crate ) fn in_new_system ( ) -> ArbiterHandle {
0 commit comments