use thread_priority::{ThreadPriority, ThreadPriorityValue};
#[derive(Debug)]
pub enum PriorityResult {
Elevated(PriorityGuard),
NotElevated {
reason: String,
},
}
pub struct PriorityGuard {
original_priority: ThreadPriority,
priority_changed: bool,
}
impl PriorityGuard {
pub fn try_elevate() -> PriorityResult {
let original_priority = match thread_priority::get_current_thread_priority() {
Ok(p) => p,
Err(e) => {
return PriorityResult::NotElevated {
reason: format!("Failed to get current thread priority: {:?}", e),
};
}
};
let target_priority = match ThreadPriorityValue::try_from(75u8) {
Ok(v) => ThreadPriority::Crossplatform(v),
Err(_) => {
return PriorityResult::NotElevated {
reason: "Failed to create valid priority value".to_string(),
};
}
};
match thread_priority::set_current_thread_priority(target_priority) {
Ok(()) => {
tracing::debug!(
"Elevated thread priority from {:?} to {:?}",
original_priority,
target_priority
);
PriorityResult::Elevated(PriorityGuard {
original_priority,
priority_changed: true,
})
}
Err(e) => {
tracing::debug!(
"Thread priority elevation failed (expected without privileges): {:?}",
e
);
PriorityResult::NotElevated {
reason: format!("Priority elevation requires elevated privileges: {:?}", e),
}
}
}
}
}
impl Drop for PriorityGuard {
fn drop(&mut self) {
if self.priority_changed {
if let Err(e) = thread_priority::set_current_thread_priority(self.original_priority) {
tracing::warn!("Failed to restore thread priority: {:?}", e);
} else {
tracing::debug!("Restored thread priority to {:?}", self.original_priority);
}
}
}
}
impl std::fmt::Debug for PriorityGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PriorityGuard")
.field("original_priority", &self.original_priority)
.field("priority_changed", &self.priority_changed)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_try_elevate() {
let result = PriorityGuard::try_elevate();
match result {
PriorityResult::Elevated(guard) => {
println!("Successfully elevated priority: {:?}", guard);
}
PriorityResult::NotElevated { reason } => {
println!(
"Priority not elevated (expected without privileges): {}",
reason
);
}
}
}
#[test]
fn test_elevate_and_restore() {
let guard = PriorityGuard::try_elevate();
if let PriorityResult::Elevated(g) = guard {
std::hint::black_box(42);
drop(g);
let guard2 = PriorityGuard::try_elevate();
match guard2 {
PriorityResult::Elevated(_) => println!("Re-elevated successfully"),
PriorityResult::NotElevated { reason } => {
println!("Re-elevation failed (ok): {}", reason)
}
}
}
}
}