#![cfg_attr(coverage_nightly, coverage(off))]
use std::fmt::Debug;
#[cfg(test)]
use std::sync::Arc;
use windows::Win32::System::JobObjects::JOBOBJECT_CPU_RATE_CONTROL_INFORMATION;
use windows::Win32::System::Kernel::PROCESSOR_NUMBER;
use windows::Win32::System::SystemInformation::{
GROUP_AFFINITY, LOGICAL_PROCESSOR_RELATIONSHIP, SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX,
};
use windows::core::Result;
#[cfg(test)]
use crate::pal::windows::MockBindings;
use crate::pal::windows::{Bindings, BuildTargetBindings};
#[derive(Clone)]
pub(crate) enum BindingsFacade {
Target(&'static BuildTargetBindings),
#[cfg(test)]
Mock(Arc<MockBindings>),
}
impl BindingsFacade {
pub(crate) const fn target() -> Self {
Self::Target(&BuildTargetBindings)
}
#[cfg(test)]
pub(crate) fn from_mock(mock: MockBindings) -> Self {
Self::Mock(Arc::new(mock))
}
}
impl Bindings for BindingsFacade {
fn get_active_processor_count(&self, group_number: u16) -> u32 {
match self {
Self::Target(bindings) => bindings.get_active_processor_count(group_number),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_active_processor_count(group_number),
}
}
fn get_maximum_processor_count(&self, group_number: u16) -> u32 {
match self {
Self::Target(bindings) => bindings.get_maximum_processor_count(group_number),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_maximum_processor_count(group_number),
}
}
fn get_maximum_processor_group_count(&self) -> u16 {
match self {
Self::Target(bindings) => bindings.get_maximum_processor_group_count(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_maximum_processor_group_count(),
}
}
fn get_current_processor_number_ex(&self) -> PROCESSOR_NUMBER {
match self {
Self::Target(bindings) => bindings.get_current_processor_number_ex(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_processor_number_ex(),
}
}
unsafe fn get_logical_processor_information_ex(
&self,
relationship_type: LOGICAL_PROCESSOR_RELATIONSHIP,
buffer: Option<*mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>,
returned_length: *mut u32,
) -> Result<()> {
match self {
Self::Target(bindings) => unsafe {
bindings.get_logical_processor_information_ex(
relationship_type,
buffer,
returned_length,
)
},
#[cfg(test)]
Self::Mock(bindings) => unsafe {
bindings.get_logical_processor_information_ex(
relationship_type,
buffer,
returned_length,
)
},
}
}
fn get_numa_highest_node_number(&self) -> u32 {
match self {
Self::Target(bindings) => bindings.get_numa_highest_node_number(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_numa_highest_node_number(),
}
}
fn get_current_process_default_cpu_set_masks(&self) -> Vec<GROUP_AFFINITY> {
match self {
Self::Target(bindings) => bindings.get_current_process_default_cpu_set_masks(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_process_default_cpu_set_masks(),
}
}
fn get_current_thread_cpu_set_masks(&self) -> Vec<GROUP_AFFINITY> {
match self {
Self::Target(bindings) => bindings.get_current_thread_cpu_set_masks(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_thread_cpu_set_masks(),
}
}
fn set_current_thread_cpu_set_masks(&self, masks: &[GROUP_AFFINITY]) {
match self {
Self::Target(bindings) => bindings.set_current_thread_cpu_set_masks(masks),
#[cfg(test)]
Self::Mock(bindings) => bindings.set_current_thread_cpu_set_masks(masks),
}
}
fn get_current_job_cpu_set_masks(&self) -> Vec<GROUP_AFFINITY> {
match self {
Self::Target(bindings) => bindings.get_current_job_cpu_set_masks(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_job_cpu_set_masks(),
}
}
fn get_current_thread_legacy_group_affinity(&self) -> GROUP_AFFINITY {
match self {
Self::Target(bindings) => bindings.get_current_thread_legacy_group_affinity(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_thread_legacy_group_affinity(),
}
}
fn get_current_job_cpu_rate_control(&self) -> Option<JOBOBJECT_CPU_RATE_CONTROL_INFORMATION> {
match self {
Self::Target(bindings) => bindings.get_current_job_cpu_rate_control(),
#[cfg(test)]
Self::Mock(bindings) => bindings.get_current_job_cpu_rate_control(),
}
}
}
#[cfg_attr(coverage_nightly, coverage(off))] impl Debug for BindingsFacade {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Target(inner) => inner.fmt(f),
#[cfg(test)]
Self::Mock(inner) => inner.fmt(f),
}
}
}