Skip to content

Commit e0a0e99

Browse files
committed
refactor(windows): migrate from winapi to windows crate and update thread priority handling
This commit updates the codebase to use the `windows` crate instead of the deprecated `winapi` crate. Key changes include: - Replaced `winapi` imports with `windows` crate equivalents. - Updated `ThreadPriorityOsValue` from `u32` to `i32` to align with the new crate's types. - Refactored thread priority handling to use the new `windows` crate enums and functions. - Improved type safety and readability by introducing new types for `IdealProcessor` and `ThreadId`.
1 parent 64ec5ab commit e0a0e99

File tree

3 files changed

+100
-85
lines changed

3 files changed

+100
-85
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ libc = ">=0.2.161"
2929

3030
[target.'cfg(windows)'.dependencies]
3131
libc = ">=0.2.123"
32-
winapi = { version = "0.3", features = ["errhandlingapi", "processthreadsapi", "winnt", "minwindef", "winbase"] }
32+
windows = { version = "0.61", features = ["Win32", "Win32_System", "Win32_System_Threading", "Win32_System_WindowsProgramming"] }

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ impl std::convert::Into<u8> for ThreadPriorityValue {
278278

279279
/// Platform-specific thread priority value.
280280
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
281-
pub struct ThreadPriorityOsValue(u32);
281+
pub struct ThreadPriorityOsValue(i32);
282282

283283
/// Thread priority enumeration.
284284
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]

src/windows.rs

Lines changed: 98 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,53 @@
44
//! the windows threads, and this module provides
55
//! better control over those.
66
7-
use winapi::ctypes::c_int;
8-
use winapi::shared::minwindef::DWORD;
9-
use winapi::um::errhandlingapi::GetLastError;
10-
use winapi::um::processthreadsapi::{
11-
GetCurrentThread, GetThreadPriority, SetThreadIdealProcessor, SetThreadPriority,
12-
SetThreadPriorityBoost,
7+
use windows::Win32::{
8+
Foundation::{GetLastError, HANDLE},
9+
System::{
10+
Threading::{
11+
GetCurrentThread, GetThreadPriority, SetThreadIdealProcessor, SetThreadPriority,
12+
SetThreadPriorityBoost, THREAD_MODE_BACKGROUND_BEGIN, THREAD_MODE_BACKGROUND_END,
13+
THREAD_PRIORITY, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_BELOW_NORMAL,
14+
THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST,
15+
THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL,
16+
},
17+
WindowsProgramming::THREAD_PRIORITY_ERROR_RETURN,
18+
},
1319
};
14-
use winapi::um::winbase;
15-
use winapi::um::winnt::HANDLE;
1620

1721
use crate::{Error, ThreadPriority};
1822

1923
/// An alias type for specifying the ideal processor.
2024
/// Used in the WinAPI for affinity control.
21-
pub type IdealProcessor = DWORD;
25+
pub type IdealProcessor = u32;
2226

2327
/// An alias type for a thread id.
24-
pub type ThreadId = HANDLE;
28+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
29+
#[repr(transparent)]
30+
pub struct ThreadId(HANDLE);
31+
32+
impl PartialOrd for ThreadId {
33+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
34+
Some(self.cmp(other))
35+
}
36+
}
37+
38+
impl Ord for ThreadId {
39+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
40+
(self.0 .0 as usize).cmp(&(other.0 .0 as usize))
41+
}
42+
}
43+
44+
impl ThreadId {
45+
/// Returns true if the thread id is invalid.
46+
pub fn is_invalid(&self) -> bool {
47+
self.0.is_invalid()
48+
}
49+
}
2550

2651
/// The WinAPI priority representation. Check out MSDN for more info:
2752
/// <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority>
28-
#[repr(u32)]
53+
#[repr(i32)]
2954
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3055
pub enum WinAPIThreadPriority {
3156
/// Begin background processing mode. The system lowers the resource
@@ -37,7 +62,7 @@ pub enum WinAPIThreadPriority {
3762
///
3863
/// # Warning
3964
/// Windows Server 2003: This value is not supported.
40-
BackgroundModeBegin = winbase::THREAD_MODE_BACKGROUND_BEGIN,
65+
BackgroundModeBegin = THREAD_MODE_BACKGROUND_BEGIN.0,
4166
/// End background processing mode. The system restores the resource
4267
/// scheduling priorities of the thread as they were before the thread
4368
/// entered background processing mode.
@@ -47,25 +72,25 @@ pub enum WinAPIThreadPriority {
4772
///
4873
/// # Warning
4974
/// Windows Server 2003: This value is not supported.
50-
BackgroundModeEnd = winbase::THREAD_MODE_BACKGROUND_END,
75+
BackgroundModeEnd = THREAD_MODE_BACKGROUND_END.0,
5176
/// Priority 1 point above the priority class.
52-
AboveNormal = winbase::THREAD_PRIORITY_ABOVE_NORMAL,
77+
AboveNormal = THREAD_PRIORITY_ABOVE_NORMAL.0,
5378
/// Priority 1 point below the priority class.
54-
BelowNormal = winbase::THREAD_PRIORITY_BELOW_NORMAL,
79+
BelowNormal = THREAD_PRIORITY_BELOW_NORMAL.0,
5580
/// Priority 2 points above the priority class.
56-
Highest = winbase::THREAD_PRIORITY_HIGHEST,
81+
Highest = THREAD_PRIORITY_HIGHEST.0,
5782
/// Base priority of 1 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS,
5883
/// NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS
5984
/// processes, and a base priority of 16 for REALTIME_PRIORITY_CLASS processes.
60-
Idle = winbase::THREAD_PRIORITY_IDLE,
85+
Idle = THREAD_PRIORITY_IDLE.0,
6186
/// Priority 2 points below the priority class.
62-
Lowest = winbase::THREAD_PRIORITY_LOWEST,
87+
Lowest = THREAD_PRIORITY_LOWEST.0,
6388
/// Normal priority for the priority class.
64-
Normal = winbase::THREAD_PRIORITY_NORMAL,
89+
Normal = THREAD_PRIORITY_NORMAL.0,
6590
/// Base priority of 15 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS,
6691
/// NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS
6792
/// processes, and a base priority of 31 for REALTIME_PRIORITY_CLASS processes.
68-
TimeCritical = winbase::THREAD_PRIORITY_TIME_CRITICAL,
93+
TimeCritical = THREAD_PRIORITY_TIME_CRITICAL.0,
6994
}
7095

7196
impl std::convert::TryFrom<ThreadPriority> for WinAPIThreadPriority {
@@ -84,16 +109,16 @@ impl std::convert::TryFrom<ThreadPriority> for WinAPIThreadPriority {
84109
99 => WinAPIThreadPriority::TimeCritical,
85110
_ => return Err(Error::Priority("The value is out of range [0; 99].")),
86111
},
87-
ThreadPriority::Os(crate::ThreadPriorityOsValue(p)) => match p {
88-
winbase::THREAD_MODE_BACKGROUND_BEGIN => WinAPIThreadPriority::BackgroundModeBegin,
89-
winbase::THREAD_MODE_BACKGROUND_END => WinAPIThreadPriority::BackgroundModeEnd,
90-
winbase::THREAD_PRIORITY_ABOVE_NORMAL => WinAPIThreadPriority::AboveNormal,
91-
winbase::THREAD_PRIORITY_BELOW_NORMAL => WinAPIThreadPriority::BelowNormal,
92-
winbase::THREAD_PRIORITY_HIGHEST => WinAPIThreadPriority::Highest,
93-
winbase::THREAD_PRIORITY_IDLE => WinAPIThreadPriority::Idle,
94-
winbase::THREAD_PRIORITY_LOWEST => WinAPIThreadPriority::Lowest,
95-
winbase::THREAD_PRIORITY_NORMAL => WinAPIThreadPriority::Normal,
96-
winbase::THREAD_PRIORITY_TIME_CRITICAL => WinAPIThreadPriority::TimeCritical,
112+
ThreadPriority::Os(crate::ThreadPriorityOsValue(p)) => match THREAD_PRIORITY(p) {
113+
THREAD_MODE_BACKGROUND_BEGIN => WinAPIThreadPriority::BackgroundModeBegin,
114+
THREAD_MODE_BACKGROUND_END => WinAPIThreadPriority::BackgroundModeEnd,
115+
THREAD_PRIORITY_ABOVE_NORMAL => WinAPIThreadPriority::AboveNormal,
116+
THREAD_PRIORITY_BELOW_NORMAL => WinAPIThreadPriority::BelowNormal,
117+
THREAD_PRIORITY_HIGHEST => WinAPIThreadPriority::Highest,
118+
THREAD_PRIORITY_IDLE => WinAPIThreadPriority::Idle,
119+
THREAD_PRIORITY_LOWEST => WinAPIThreadPriority::Lowest,
120+
THREAD_PRIORITY_NORMAL => WinAPIThreadPriority::Normal,
121+
THREAD_PRIORITY_TIME_CRITICAL => WinAPIThreadPriority::TimeCritical,
97122
_ => {
98123
return Err(Error::Priority(
99124
"The value is out of range of allowed values.",
@@ -105,28 +130,28 @@ impl std::convert::TryFrom<ThreadPriority> for WinAPIThreadPriority {
105130
}
106131
}
107132

108-
impl std::convert::TryFrom<DWORD> for WinAPIThreadPriority {
133+
impl std::convert::TryFrom<THREAD_PRIORITY> for WinAPIThreadPriority {
109134
type Error = crate::Error;
110135

111-
fn try_from(priority: DWORD) -> Result<Self, Self::Error> {
136+
fn try_from(priority: THREAD_PRIORITY) -> Result<Self, Self::Error> {
112137
Ok(match priority {
113-
winbase::THREAD_MODE_BACKGROUND_BEGIN => WinAPIThreadPriority::BackgroundModeBegin,
114-
winbase::THREAD_MODE_BACKGROUND_END => WinAPIThreadPriority::BackgroundModeEnd,
115-
winbase::THREAD_PRIORITY_ABOVE_NORMAL => WinAPIThreadPriority::AboveNormal,
116-
winbase::THREAD_PRIORITY_BELOW_NORMAL => WinAPIThreadPriority::BelowNormal,
117-
winbase::THREAD_PRIORITY_HIGHEST => WinAPIThreadPriority::Highest,
118-
winbase::THREAD_PRIORITY_IDLE => WinAPIThreadPriority::Idle,
119-
winbase::THREAD_PRIORITY_LOWEST => WinAPIThreadPriority::Lowest,
120-
winbase::THREAD_PRIORITY_NORMAL => WinAPIThreadPriority::Normal,
121-
winbase::THREAD_PRIORITY_TIME_CRITICAL => WinAPIThreadPriority::TimeCritical,
138+
THREAD_MODE_BACKGROUND_BEGIN => WinAPIThreadPriority::BackgroundModeBegin,
139+
THREAD_MODE_BACKGROUND_END => WinAPIThreadPriority::BackgroundModeEnd,
140+
THREAD_PRIORITY_ABOVE_NORMAL => WinAPIThreadPriority::AboveNormal,
141+
THREAD_PRIORITY_BELOW_NORMAL => WinAPIThreadPriority::BelowNormal,
142+
THREAD_PRIORITY_HIGHEST => WinAPIThreadPriority::Highest,
143+
THREAD_PRIORITY_IDLE => WinAPIThreadPriority::Idle,
144+
THREAD_PRIORITY_LOWEST => WinAPIThreadPriority::Lowest,
145+
THREAD_PRIORITY_NORMAL => WinAPIThreadPriority::Normal,
146+
THREAD_PRIORITY_TIME_CRITICAL => WinAPIThreadPriority::TimeCritical,
122147
_ => return Err(Error::Priority("Priority couldn't be parsed")),
123148
})
124149
}
125150
}
126151

127152
impl From<WinAPIThreadPriority> for crate::ThreadPriorityOsValue {
128153
fn from(p: WinAPIThreadPriority) -> Self {
129-
crate::ThreadPriorityOsValue(p as u32)
154+
crate::ThreadPriorityOsValue(p as u32 as i32)
130155
}
131156
}
132157

@@ -173,11 +198,8 @@ pub fn set_winapi_thread_priority(
173198
priority: WinAPIThreadPriority,
174199
) -> Result<(), Error> {
175200
unsafe {
176-
if SetThreadPriority(native, priority as c_int) != 0 {
177-
Ok(())
178-
} else {
179-
Err(Error::OS(GetLastError() as i32))
180-
}
201+
SetThreadPriority(native.0, THREAD_PRIORITY(priority as i32))
202+
.map_err(|e| Error::OS(e.code().0))
181203
}
182204
}
183205

@@ -198,7 +220,6 @@ pub fn set_winapi_thread_priority(
198220
///
199221
/// If there's an error, a result of
200222
/// [`GetLastError`](https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) is returned.
201-
202223
pub fn set_current_thread_priority(priority: ThreadPriority) -> Result<(), Error> {
203224
let thread_id = thread_native_id();
204225
set_thread_priority(thread_id, priority)
@@ -217,13 +238,13 @@ pub fn set_current_thread_priority(priority: ThreadPriority) -> Result<(), Error
217238
/// ```
218239
pub fn get_thread_priority(native: ThreadId) -> Result<ThreadPriority, Error> {
219240
unsafe {
220-
let ret = GetThreadPriority(native);
221-
if ret as u32 != winbase::THREAD_PRIORITY_ERROR_RETURN {
222-
Ok(ThreadPriority::Os(crate::ThreadPriorityOsValue(
223-
WinAPIThreadPriority::try_from(ret as DWORD)? as u32,
241+
let ret = GetThreadPriority(native.0);
242+
if ret as u32 != THREAD_PRIORITY_ERROR_RETURN {
243+
Ok(ThreadPriority::Os(crate::ThreadPriorityOsValue::from(
244+
WinAPIThreadPriority::try_from(THREAD_PRIORITY(ret))?,
224245
)))
225246
} else {
226-
Err(Error::OS(GetLastError() as i32))
247+
Err(Error::OS(GetLastError().0 as i32))
227248
}
228249
}
229250
}
@@ -241,13 +262,13 @@ pub fn get_thread_priority(native: ThreadId) -> Result<ThreadPriority, Error> {
241262
/// ```
242263
pub fn get_current_thread_priority() -> Result<ThreadPriority, Error> {
243264
unsafe {
244-
let ret = GetThreadPriority(thread_native_id());
245-
if ret as u32 != winbase::THREAD_PRIORITY_ERROR_RETURN {
246-
Ok(ThreadPriority::Os(crate::ThreadPriorityOsValue(
247-
WinAPIThreadPriority::try_from(ret as DWORD)? as u32,
265+
let ret = GetThreadPriority(thread_native_id().0);
266+
if ret as u32 != THREAD_PRIORITY_ERROR_RETURN {
267+
Ok(ThreadPriority::Os(crate::ThreadPriorityOsValue::from(
268+
WinAPIThreadPriority::try_from(THREAD_PRIORITY(ret))?,
248269
)))
249270
} else {
250-
Err(Error::OS(GetLastError() as i32))
271+
Err(Error::OS(GetLastError().0 as i32))
251272
}
252273
}
253274
}
@@ -261,10 +282,10 @@ pub fn get_current_thread_priority() -> Result<ThreadPriority, Error> {
261282
/// ```rust
262283
/// use thread_priority::thread_native_id;
263284
///
264-
/// assert!(!thread_native_id().is_null());
285+
/// assert!(!thread_native_id().is_invalid());
265286
/// ```
266287
pub fn thread_native_id() -> ThreadId {
267-
unsafe { GetCurrentThread() }
288+
ThreadId(unsafe { GetCurrentThread() })
268289
}
269290

270291
/// Disables or enables the ability of the system to temporarily boost the priority of a thread.
@@ -281,13 +302,7 @@ pub fn thread_native_id() -> ThreadId {
281302
/// assert!(set_thread_priority_boost(thread_id, false).is_ok())
282303
/// ```
283304
pub fn set_thread_priority_boost(native: ThreadId, enabled: bool) -> Result<(), Error> {
284-
unsafe {
285-
if SetThreadPriorityBoost(native, enabled as i32) != 0 {
286-
Ok(())
287-
} else {
288-
Err(Error::OS(GetLastError() as i32))
289-
}
290-
}
305+
unsafe { SetThreadPriorityBoost(native.0, enabled).map_err(|e| Error::OS(e.code().0)) }
291306
}
292307

293308
/// Disables or enables the ability of the system to temporarily boost the priority of a current thread.
@@ -327,9 +342,9 @@ pub fn set_thread_ideal_processor(
327342
ideal_processor: IdealProcessor,
328343
) -> Result<IdealProcessor, Error> {
329344
unsafe {
330-
let ret = SetThreadIdealProcessor(native, ideal_processor);
331-
if ret == IdealProcessor::max_value() - 1 {
332-
Err(Error::OS(GetLastError() as i32))
345+
let ret = SetThreadIdealProcessor(native.0, ideal_processor);
346+
if ret == u32::MAX {
347+
Err(Error::OS(GetLastError().0 as i32))
333348
} else {
334349
Ok(ret)
335350
}
@@ -346,20 +361,20 @@ pub fn set_current_thread_ideal_processor(
346361
set_thread_ideal_processor(thread_native_id(), ideal_processor)
347362
}
348363

349-
impl std::convert::TryFrom<u32> for crate::ThreadPriorityOsValue {
364+
impl std::convert::TryFrom<i32> for crate::ThreadPriorityOsValue {
350365
type Error = ();
351366

352-
fn try_from(value: u32) -> Result<Self, Self::Error> {
353-
Ok(crate::ThreadPriorityOsValue(match value {
354-
winbase::THREAD_MODE_BACKGROUND_BEGIN
355-
| winbase::THREAD_MODE_BACKGROUND_END
356-
| winbase::THREAD_PRIORITY_ABOVE_NORMAL
357-
| winbase::THREAD_PRIORITY_BELOW_NORMAL
358-
| winbase::THREAD_PRIORITY_HIGHEST
359-
| winbase::THREAD_PRIORITY_IDLE
360-
| winbase::THREAD_PRIORITY_LOWEST
361-
| winbase::THREAD_PRIORITY_NORMAL
362-
| winbase::THREAD_PRIORITY_TIME_CRITICAL => value,
367+
fn try_from(value: i32) -> Result<Self, Self::Error> {
368+
Ok(crate::ThreadPriorityOsValue(match THREAD_PRIORITY(value) {
369+
THREAD_MODE_BACKGROUND_BEGIN
370+
| THREAD_MODE_BACKGROUND_END
371+
| THREAD_PRIORITY_ABOVE_NORMAL
372+
| THREAD_PRIORITY_BELOW_NORMAL
373+
| THREAD_PRIORITY_HIGHEST
374+
| THREAD_PRIORITY_IDLE
375+
| THREAD_PRIORITY_LOWEST
376+
| THREAD_PRIORITY_NORMAL
377+
| THREAD_PRIORITY_TIME_CRITICAL => value,
363378
_ => return Err(()),
364379
}))
365380
}
@@ -397,7 +412,7 @@ pub trait ThreadExt {
397412
/// ```rust
398413
/// use thread_priority::*;
399414
///
400-
/// assert!(!std::thread::current().get_native_id().unwrap().is_null());
415+
/// assert!(!std::thread::current().get_native_id().unwrap().is_invalid());
401416
/// ```
402417
fn get_native_id(&self) -> Result<ThreadId, Error>;
403418

0 commit comments

Comments
 (0)