use core::mem;
use std::marker::PhantomData;
use windows_sys::Win32::System::Threading::{
PTP_CLEANUP_GROUP, PTP_CLEANUP_GROUP_CANCEL_CALLBACK, TP_CALLBACK_ENVIRON_V3,
TP_CALLBACK_ENVIRON_V3_0, TP_CALLBACK_PRIORITY, TP_CALLBACK_PRIORITY_HIGH,
TP_CALLBACK_PRIORITY_LOW, TP_CALLBACK_PRIORITY_NORMAL,
};
use crate::pool::ThreadpoolPool;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CallbackPriority {
High,
Normal,
Low,
}
impl CallbackPriority {
fn to_win32(self) -> TP_CALLBACK_PRIORITY {
match self {
Self::High => TP_CALLBACK_PRIORITY_HIGH,
Self::Normal => TP_CALLBACK_PRIORITY_NORMAL,
Self::Low => TP_CALLBACK_PRIORITY_LOW,
}
}
}
mod environ_flags {
pub(super) const LONG_FUNCTION: u32 = 1 << 0;
}
const ENVIRON_VERSION: u32 = 3;
pub struct CallbackEnviron<'pool> {
inner: TP_CALLBACK_ENVIRON_V3,
pool: PhantomData<&'pool ThreadpoolPool>,
}
impl<'pool> CallbackEnviron<'pool> {
pub fn new() -> Self {
Self {
inner: TP_CALLBACK_ENVIRON_V3 {
Version: ENVIRON_VERSION,
Pool: 0,
CleanupGroup: 0,
CleanupGroupCancelCallback: None,
RaceDll: core::ptr::null_mut(),
ActivationContext: 0,
FinalizationCallback: None,
u: TP_CALLBACK_ENVIRON_V3_0 { Flags: 0 },
CallbackPriority: TP_CALLBACK_PRIORITY_NORMAL,
Size: mem::size_of::<TP_CALLBACK_ENVIRON_V3>() as u32,
},
pool: PhantomData,
}
}
pub fn set_pool(&mut self, pool: &'pool ThreadpoolPool) {
self.inner.Pool = pool.as_raw();
}
pub fn clear_pool(&mut self) {
self.inner.Pool = 0;
}
pub unsafe fn set_cleanup_group(
&mut self,
group: PTP_CLEANUP_GROUP,
cancel_callback: PTP_CLEANUP_GROUP_CANCEL_CALLBACK,
) {
self.inner.CleanupGroup = group;
self.inner.CleanupGroupCancelCallback = cancel_callback;
}
pub fn set_priority(&mut self, priority: CallbackPriority) {
self.inner.CallbackPriority = priority.to_win32();
}
pub fn set_runs_long(&mut self) {
unsafe { self.inner.u.Flags |= environ_flags::LONG_FUNCTION }
}
pub unsafe fn set_library(&mut self, dll: *mut core::ffi::c_void) {
self.inner.RaceDll = dll;
}
pub(crate) fn from_inner(inner: TP_CALLBACK_ENVIRON_V3) -> Self {
Self {
inner,
pool: PhantomData,
}
}
pub fn as_mut_ptr(&mut self) -> *mut TP_CALLBACK_ENVIRON_V3 {
&raw mut self.inner
}
pub fn as_inner(&self) -> &TP_CALLBACK_ENVIRON_V3 {
&self.inner
}
}
impl Default for CallbackEnviron<'_> {
fn default() -> Self {
Self::new()
}
}
impl Drop for CallbackEnviron<'_> {
fn drop(&mut self) {
}
}
#[cfg(test)]
mod tests;