1#![feature(thread_spawn_unchecked)]
2#![feature(test)]
3
4use std::thread;
5use std::marker::PhantomData;
6use std::io;
7
8struct JoinFlag {
9 is_joined: bool,
10}
11
12impl JoinFlag {
13 fn new() -> Self {
14 Self {
15 is_joined: false,
16 }
17 }
18
19 fn set_join(mut self) {
20 self.is_joined = true;
21 }
22}
23
24impl Drop for JoinFlag {
25 #[inline]
26 fn drop(&mut self) {
27 if !self.is_joined {
28 panic!("handle must be join before dropped")
29 }
30 }
31}
32
33pub struct BorrowedJoinHandle<'b, T> {
34 inner: thread::JoinHandle<T>,
35 join_flag: JoinFlag,
36 _marker: PhantomData<&'b ()>,
37}
38
39impl<'b, T> From<thread::JoinHandle<T>> for BorrowedJoinHandle<'b, T> {
40
41 #[inline]
42 fn from(handle: thread::JoinHandle<T>) -> Self {
43 Self::new(handle)
44 }
45}
46
47impl<'b, T> BorrowedJoinHandle<'b, T> {
48
49 #[inline]
50 fn new(inner: thread::JoinHandle<T>) -> Self {
51 Self {
52 inner,
53 join_flag: JoinFlag::new(),
54 _marker: PhantomData,
55 }
56 }
57
58 #[inline]
59 pub fn thread(&self) -> &thread::Thread {
60 self.inner.thread()
61 }
62
63 #[inline]
64 pub fn join(self) -> thread::Result<T> {
65 self.join_flag.set_join();
66 self.inner.join()
67 }
68}
69
70#[inline]
71pub fn spawn_with<'b, F, T>(builder: thread::Builder, f: F) -> io::Result<BorrowedJoinHandle<'b, T>>
72 where
73 F: FnOnce() -> T,
74 F: Send + 'b,
75 T: Send + 'b, {
76 unsafe {
77 match builder.spawn_unchecked(f) {
78 Ok(handle) => Ok(handle.into()),
79 Err(err) => Err(err),
80 }
81 }
82}
83
84#[inline]
85pub fn spawn<'b, F, T>(f: F) -> BorrowedJoinHandle<'b, T>
86where
87 F: FnOnce() -> T,
88 F: Send + 'b,
89 T: Send + 'b,
90{
91 spawn_with(thread::Builder::new(), f).unwrap()
92}
93
94#[cfg(test)]
95mod tests;
96
97#[cfg(test)]
98mod bench;