use std::io::{Error, Result};
use std::time::Duration;
use super::bindings::{
mach_port_t, mach_thread_self, thread_basic_info, thread_info, thread_info_t, KERN_SUCCESS,
THREAD_BASIC_INFO, THREAD_BASIC_INFO_COUNT,
};
use std::mem::MaybeUninit;
use crate::Clock;
pub struct Thread(mach_port_t);
impl Thread {
pub fn get_basic_info(&self) -> Result<thread_basic_info> {
let mut info = MaybeUninit::<thread_basic_info>::zeroed();
let s = unsafe {
thread_info(
self.0,
THREAD_BASIC_INFO,
info.as_mut_ptr() as thread_info_t,
&mut THREAD_BASIC_INFO_COUNT,
)
};
if s != KERN_SUCCESS {
return Err(Error::last_os_error());
}
let info = unsafe { info.assume_init() };
Ok(info)
}
pub fn get_user_time(&self) -> Result<Duration> {
let info = self.get_basic_info()?;
let time = Duration::from(info.user_time);
Ok(time)
}
pub fn get_system_time(&self) -> Result<Duration> {
let info = self.get_basic_info()?;
let time = Duration::from(info.system_time);
Ok(time)
}
pub fn get_cpu_time(&self) -> Result<Duration> {
let info = self.get_basic_info()?;
let time = Duration::from(info.user_time) + Duration::from(info.system_time);
Ok(time)
}
pub fn current() -> Thread {
Thread(unsafe { mach_thread_self() }) }
}
pub struct ThreadCPUClock(Thread);
impl Clock for ThreadCPUClock {
fn get_time(&self) -> Result<Duration> {
self.0.get_cpu_time()
}
}
impl From<Thread> for ThreadCPUClock {
fn from(thread: Thread) -> ThreadCPUClock {
ThreadCPUClock(thread)
}
}
pub fn cpu_clock_for_current_thread() -> Result<ThreadCPUClock> {
Ok(Thread::current().into())
}