1use std::fmt;
19
20pub use crate::intent::ThreadIntent;
21pub use crate::pool::Pool;
22
23mod intent;
24mod pool;
25
26pub fn spawn<F, T>(intent: ThreadIntent, name: String, f: F) -> JoinHandle<T>
30where
31 F: (FnOnce() -> T) + Send + 'static,
32 T: Send + 'static,
33{
34 Builder::new(intent, name)
35 .spawn(f)
36 .expect("failed to spawn thread")
37}
38
39pub struct Builder {
40 intent: ThreadIntent,
41 inner: jod_thread::Builder,
42 allow_leak: bool,
43}
44
45impl Builder {
46 #[must_use]
47 pub fn new(intent: ThreadIntent, name: impl Into<String>) -> Self {
48 Self {
49 intent,
50 inner: jod_thread::Builder::new().name(name.into()),
51 allow_leak: false,
52 }
53 }
54
55 #[must_use]
56 pub fn stack_size(self, size: usize) -> Self {
57 Self {
58 inner: self.inner.stack_size(size),
59 ..self
60 }
61 }
62
63 #[must_use]
66 pub fn allow_leak(self, allow_leak: bool) -> Self {
67 Self { allow_leak, ..self }
68 }
69
70 pub fn spawn<F, T>(self, f: F) -> std::io::Result<JoinHandle<T>>
71 where
72 F: (FnOnce() -> T) + Send + 'static,
73 T: Send + 'static,
74 {
75 let inner_handle = self.inner.spawn(move || {
76 self.intent.apply_to_current_thread();
77 f()
78 })?;
79
80 Ok(JoinHandle {
81 inner: Some(inner_handle),
82 allow_leak: self.allow_leak,
83 })
84 }
85}
86
87pub struct JoinHandle<T = ()> {
88 inner: Option<jod_thread::JoinHandle<T>>,
91 allow_leak: bool,
92}
93
94impl<T> JoinHandle<T> {
95 #[must_use]
99 pub fn join(mut self) -> T {
100 self.inner.take().unwrap().join()
101 }
102}
103
104impl<T> Drop for JoinHandle<T> {
105 fn drop(&mut self) {
106 if !self.allow_leak {
107 return;
108 }
109
110 if let Some(join_handle) = self.inner.take() {
111 join_handle.detach();
112 }
113 }
114}
115
116impl<T> fmt::Debug for JoinHandle<T> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.pad("JoinHandle { .. }")
119 }
120}