heim_cpu/sys/windows/wrappers/
count.rs1use std::io;
2use std::ptr;
3
4use winapi::shared::{minwindef, winerror};
5use winapi::um::{sysinfoapi, winnt};
6
7#[derive(Debug)]
15pub struct LogicalProcessors {
16 buffer: Vec<u8>,
17}
18
19impl LogicalProcessors {
20 #[allow(clippy::cast_ptr_alignment)]
24 pub fn get() -> io::Result<Self> {
25 let mut buffer = vec![];
26 let mut buffer_size = 0u32;
27
28 let result = unsafe {
29 sysinfoapi::GetLogicalProcessorInformationEx(
30 winnt::RelationAll,
31 ptr::null_mut(),
32 &mut buffer_size,
33 )
34 };
35 debug_assert_eq!(result, minwindef::FALSE);
36
37 loop {
38 buffer.reserve(buffer_size as usize - buffer.capacity());
40
41 let result = unsafe {
42 sysinfoapi::GetLogicalProcessorInformationEx(
43 winnt::RelationAll,
44 buffer.as_mut_ptr() as *mut _,
45 &mut buffer_size,
46 )
47 };
48
49 if result == minwindef::FALSE {
50 let e = io::Error::last_os_error();
51 match e.raw_os_error() {
52 Some(value) if value == winerror::ERROR_INSUFFICIENT_BUFFER as i32 => continue,
55 _ => return Err(e),
56 }
57 } else {
58 unsafe {
59 buffer.set_len(buffer_size as usize);
60 }
61 break;
62 }
63 }
64
65 Ok(Self { buffer })
66 }
67
68 pub fn iter(&self) -> LogicalProcessorsIter<'_> {
69 LogicalProcessorsIter {
70 data: &self.buffer,
71 offset: 0,
72 }
73 }
74}
75
76#[derive(Debug)]
77pub struct LogicalProcessorsIter<'p> {
78 data: &'p [u8],
79 offset: usize,
80}
81
82impl<'p> Iterator for LogicalProcessorsIter<'p> {
83 type Item = &'p winnt::SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
84
85 #[allow(clippy::cast_ptr_alignment)]
86 fn next(&mut self) -> Option<Self::Item> {
87 if self.offset >= self.data.len() {
88 return None;
89 }
90
91 let core = unsafe {
92 let ptr = self.data.as_ptr().add(self.offset)
93 as winnt::PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
94 self.offset += (*ptr).Size as usize;
95 &*ptr
96 };
97 Some(core)
98 }
99}