stop_thread/
lib.rs

1#![feature(doc_cfg)]
2
3// clippy doesn't see the cfg(doc) version, and adding docs to the others would
4// likely lead to issues with macro_rules transcriber repeater nesting limitations
5#![allow(clippy::missing_safety_doc)]
6
7// #![feature(trace_macros)]
8// trace_macros!(true);
9
10use std::thread::JoinHandle;
11
12macro_rules! unbracket {
13    (_ [$($tt1:tt)*]) => { $($tt1)* };
14    (() [$($tt1:tt)*]) => { ($($tt1)*) };
15    ([] [$($tt1:tt)*]) => { [$($tt1)*] };
16    ({} [$($tt1:tt)*]) => { {$($tt1)*} };
17    ($tt0:tt [$($tt1:tt)*] @unbracket ($($tt2:tt)*) $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
18    ($tt0:tt [$($tt1:tt)*] @unbracket [$($tt2:tt)*] $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
19    ($tt0:tt [$($tt1:tt)*] @unbracket {$($tt2:tt)*} $($tt3:tt)*) => { unbracket!{ $tt0 [$($tt1)* $($tt2)*] $($tt3)*} };
20    ($tt0:tt [$($tt1:tt)*] $tt2:tt $($tt3:tt)*) => { unbracket!{$tt0 [$($tt1)* $tt2] $($tt3)*} };
21}
22
23macro_rules! cfg_doc {
24    ($(#[doc=$doc0:literal])+ decl: $decl:tt $($($(#[doc=$doc1:literal])+)? if $cfg:tt $body:tt)*) => {
25        unbracket! {_ []
26            #[cfg(doc)]
27            #[doc(cfg(any($($cfg),*)))]
28            $(#[doc=$doc0])+
29            $($(
30                $(#[doc=$doc1])+
31            )?)*
32            @unbracket $decl {
33                unimplemented!("Documentation implementation!");
34            }
35
36            $(
37                #[cfg(all(not(doc), $cfg))]
38                @unbracket $decl
39                    $body
40            )*
41        }
42    }
43}
44
45cfg_doc! {
46    /// Only kills the thread if it has enabled cancellation, then performs cleanup.
47    /// See `man pthread_cancel` for more information.
48    /// 
49    /// # Safety
50    ///
51    /// See `man pthread_cancel`.
52    
53    decl: [pub unsafe fn kill_thread_graceful<T>(handle: JoinHandle<T>)]
54    
55    if unix {
56        use std::os::unix::thread::JoinHandleExt;
57        use libc::pthread_cancel;
58
59        let raw_handle = handle.into_pthread_t();
60        pthread_cancel(raw_handle);
61    }
62}
63
64cfg_doc! {
65    /// Forcibly and immediately stops the thread, without any cleanup.
66    /// 
67    /// # Safety
68    ///
69    /// See <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread>.
70    
71    decl: [pub unsafe fn kill_thread_forcibly_exit_code<T>(handle: JoinHandle<T>, exit_code: u32)]
72    
73    if windows {
74        use std::os::windows::io::IntoRawHandle;
75        use winapi::um::processthreadsapi::TerminateThread;
76        use winapi::ctypes::c_void as winapi_c_void;
77
78        let raw_handle = handle.into_raw_handle();
79        TerminateThread(raw_handle as *mut winapi_c_void, exit_code);
80    }
81}
82
83cfg_doc! {
84    /// Suspends the thread.
85    /// 
86    /// # Safety
87    /// 
88    /// See <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread>.
89    
90    decl: [pub unsafe fn suspend_thread<T>(handle: JoinHandle<T>)] 
91    
92    if windows {
93        use std::os::windows::io::IntoRawHandle;
94        use winapi::um::processthreadsapi::SuspendThread;
95        use winapi::ctypes::c_void as winapi_c_void;
96        
97        let raw_handle = handle.into_raw_handle();
98        SuspendThread(raw_handle as *mut winapi_c_void);
99    }
100}