std/thread/builder.rs
1use super::join_handle::JoinHandle;
2use super::lifecycle::spawn_unchecked;
3use crate::io;
4
5/// Thread factory, which can be used in order to configure the properties of
6/// a new thread.
7///
8/// Methods can be chained on it in order to configure it.
9///
10/// The two configurations available are:
11///
12/// - [`name`]: specifies an [associated name for the thread][naming-threads]
13/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size]
14///
15/// The [`spawn`] method will take ownership of the builder and create an
16/// [`io::Result`] to the thread handle with the given configuration.
17///
18/// The [`thread::spawn`] free function uses a `Builder` with default
19/// configuration and [`unwrap`]s its return value.
20///
21/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want
22/// to recover from a failure to launch a thread, indeed the free function will
23/// panic where the `Builder` method will return a [`io::Result`].
24///
25/// # Examples
26///
27/// ```
28/// use std::thread;
29///
30/// let builder = thread::Builder::new();
31///
32/// let handler = builder.spawn(|| {
33/// // thread code
34/// }).unwrap();
35///
36/// handler.join().unwrap();
37/// ```
38///
39/// [`stack_size`]: Builder::stack_size
40/// [`name`]: Builder::name
41/// [`spawn`]: Builder::spawn
42/// [`thread::spawn`]: super::spawn
43/// [`io::Result`]: crate::io::Result
44/// [`unwrap`]: crate::result::Result::unwrap
45/// [naming-threads]: ./index.html#naming-threads
46/// [stack-size]: ./index.html#stack-size
47#[must_use = "must eventually spawn the thread"]
48#[stable(feature = "rust1", since = "1.0.0")]
49#[derive(Debug)]
50pub struct Builder {
51 /// A name for the thread-to-be, for identification in panic messages
52 pub(super) name: Option<String>,
53 /// The size of the stack for the spawned thread in bytes
54 pub(super) stack_size: Option<usize>,
55 /// Skip running and inheriting the thread spawn hooks
56 pub(super) no_hooks: bool,
57}
58
59impl Builder {
60 /// Generates the base configuration for spawning a thread, from which
61 /// configuration methods can be chained.
62 ///
63 /// # Examples
64 ///
65 /// ```
66 /// use std::thread;
67 ///
68 /// let builder = thread::Builder::new()
69 /// .name("foo".into())
70 /// .stack_size(32 * 1024);
71 ///
72 /// let handler = builder.spawn(|| {
73 /// // thread code
74 /// }).unwrap();
75 ///
76 /// handler.join().unwrap();
77 /// ```
78 #[stable(feature = "rust1", since = "1.0.0")]
79 pub fn new() -> Builder {
80 Builder { name: None, stack_size: None, no_hooks: false }
81 }
82
83 /// Names the thread-to-be. Currently the name is used for identification
84 /// only in panic messages.
85 ///
86 /// The name must not contain null bytes (`\0`).
87 ///
88 /// For more information about named threads, see
89 /// [this module-level documentation][naming-threads].
90 ///
91 /// # Examples
92 ///
93 /// ```
94 /// use std::thread;
95 ///
96 /// let builder = thread::Builder::new()
97 /// .name("foo".into());
98 ///
99 /// let handler = builder.spawn(|| {
100 /// assert_eq!(thread::current().name(), Some("foo"))
101 /// }).unwrap();
102 ///
103 /// handler.join().unwrap();
104 /// ```
105 ///
106 /// [naming-threads]: ./index.html#naming-threads
107 #[stable(feature = "rust1", since = "1.0.0")]
108 pub fn name(mut self, name: String) -> Builder {
109 self.name = Some(name);
110 self
111 }
112
113 /// Sets the size of the stack (in bytes) for the new thread.
114 ///
115 /// The actual stack size may be greater than this value if
116 /// the platform specifies a minimal stack size.
117 ///
118 /// For more information about the stack size for threads, see
119 /// [this module-level documentation][stack-size].
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use std::thread;
125 ///
126 /// let builder = thread::Builder::new().stack_size(32 * 1024);
127 /// ```
128 ///
129 /// [stack-size]: ./index.html#stack-size
130 #[stable(feature = "rust1", since = "1.0.0")]
131 pub fn stack_size(mut self, size: usize) -> Builder {
132 self.stack_size = Some(size);
133 self
134 }
135
136 /// Disables running and inheriting [spawn hooks].
137 ///
138 /// Use this if the parent thread is in no way relevant for the child thread.
139 /// For example, when lazily spawning threads for a thread pool.
140 ///
141 /// [spawn hooks]: super::add_spawn_hook
142 #[unstable(feature = "thread_spawn_hook", issue = "132951")]
143 pub fn no_hooks(mut self) -> Builder {
144 self.no_hooks = true;
145 self
146 }
147
148 /// Spawns a new thread by taking ownership of the `Builder`, and returns an
149 /// [`io::Result`] to its [`JoinHandle`].
150 ///
151 /// The spawned thread may outlive the caller (unless the caller thread
152 /// is the main thread; the whole process is terminated when the main
153 /// thread finishes). The join handle can be used to block on
154 /// termination of the spawned thread, including recovering its panics.
155 ///
156 /// For a more complete documentation see [`thread::spawn`].
157 ///
158 /// # Errors
159 ///
160 /// Unlike the [`spawn`] free function, this method yields an
161 /// [`io::Result`] to capture any failure to create the thread at
162 /// the OS level.
163 ///
164 /// [`io::Result`]: crate::io::Result
165 ///
166 /// # Panics
167 ///
168 /// Panics if a thread name was set and it contained null bytes.
169 ///
170 /// # Examples
171 ///
172 /// ```
173 /// use std::thread;
174 ///
175 /// let builder = thread::Builder::new();
176 ///
177 /// let handler = builder.spawn(|| {
178 /// // thread code
179 /// }).unwrap();
180 ///
181 /// handler.join().unwrap();
182 /// ```
183 ///
184 /// [`thread::spawn`]: super::spawn
185 /// [`spawn`]: super::spawn
186 #[stable(feature = "rust1", since = "1.0.0")]
187 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
188 pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
189 where
190 F: FnOnce() -> T,
191 F: Send + 'static,
192 T: Send + 'static,
193 {
194 unsafe { self.spawn_unchecked(f) }
195 }
196
197 /// Spawns a new thread without any lifetime restrictions by taking ownership
198 /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`].
199 ///
200 /// The spawned thread may outlive the caller (unless the caller thread
201 /// is the main thread; the whole process is terminated when the main
202 /// thread finishes). The join handle can be used to block on
203 /// termination of the spawned thread, including recovering its panics.
204 ///
205 /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`],
206 /// except for the relaxed lifetime bounds, which render it unsafe.
207 /// For a more complete documentation see [`thread::spawn`].
208 ///
209 /// # Errors
210 ///
211 /// Unlike the [`spawn`] free function, this method yields an
212 /// [`io::Result`] to capture any failure to create the thread at
213 /// the OS level.
214 ///
215 /// # Panics
216 ///
217 /// Panics if a thread name was set and it contained null bytes.
218 ///
219 /// # Safety
220 ///
221 /// The caller has to ensure that the spawned thread does not outlive any
222 /// references in the supplied thread closure and its return type.
223 /// This can be guaranteed in two ways:
224 ///
225 /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced
226 /// data is dropped
227 /// - use only types with `'static` lifetime bounds, i.e., those with no or only
228 /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`]
229 /// and [`thread::spawn`] enforce this property statically)
230 ///
231 /// # Examples
232 ///
233 /// ```
234 /// use std::thread;
235 ///
236 /// let builder = thread::Builder::new();
237 ///
238 /// let x = 1;
239 /// let thread_x = &x;
240 ///
241 /// let handler = unsafe {
242 /// builder.spawn_unchecked(move || {
243 /// println!("x = {}", *thread_x);
244 /// }).unwrap()
245 /// };
246 ///
247 /// // caller has to ensure `join()` is called, otherwise
248 /// // it is possible to access freed memory if `x` gets
249 /// // dropped before the thread closure is executed!
250 /// handler.join().unwrap();
251 /// ```
252 ///
253 /// [`io::Result`]: crate::io::Result
254 /// [`thread::spawn`]: super::spawn
255 /// [`spawn`]: super::spawn
256 #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")]
257 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
258 pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
259 where
260 F: FnOnce() -> T,
261 F: Send,
262 T: Send,
263 {
264 let Builder { name, stack_size, no_hooks } = self;
265 Ok(JoinHandle(unsafe { spawn_unchecked(name, stack_size, no_hooks, None, f) }?))
266 }
267}