(
handle_seq: PyObjectRef,
wait_all: bool,
milliseconds: OptionalArg<u32>,
vm: &VirtualMachine,
)
| 1564 | /// BatchedWaitForMultipleObjects - Wait for multiple handles, supporting more than 64. |
| 1565 | #[pyfunction] |
| 1566 | fn BatchedWaitForMultipleObjects( |
| 1567 | handle_seq: PyObjectRef, |
| 1568 | wait_all: bool, |
| 1569 | milliseconds: OptionalArg<u32>, |
| 1570 | vm: &VirtualMachine, |
| 1571 | ) -> PyResult<PyObjectRef> { |
| 1572 | use alloc::sync::Arc; |
| 1573 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 1574 | use windows_sys::Win32::Foundation::{CloseHandle, WAIT_FAILED, WAIT_OBJECT_0}; |
| 1575 | use windows_sys::Win32::System::SystemInformation::GetTickCount64; |
| 1576 | use windows_sys::Win32::System::Threading::{ |
| 1577 | CreateEventW as WinCreateEventW, CreateThread, GetExitCodeThread, |
| 1578 | INFINITE as WIN_INFINITE, ResumeThread, SetEvent as WinSetEvent, TerminateThread, |
| 1579 | WaitForMultipleObjects, |
| 1580 | }; |
| 1581 | |
| 1582 | let milliseconds = milliseconds.unwrap_or(WIN_INFINITE); |
| 1583 | |
| 1584 | // Get handles from sequence |
| 1585 | let seq = ArgSequence::<isize>::try_from_object(vm, handle_seq)?; |
| 1586 | let handles: Vec<isize> = seq.into_vec(); |
| 1587 | let nhandles = handles.len(); |
| 1588 | |
| 1589 | if nhandles == 0 { |
| 1590 | return if wait_all { |
| 1591 | Ok(vm.ctx.none()) |
| 1592 | } else { |
| 1593 | Ok(vm.ctx.new_list(vec![]).into()) |
| 1594 | }; |
| 1595 | } |
| 1596 | |
| 1597 | let max_total_objects = (MAXIMUM_WAIT_OBJECTS - 1) * (MAXIMUM_WAIT_OBJECTS - 1); |
| 1598 | if nhandles > max_total_objects { |
| 1599 | return Err(vm.new_value_error(format!( |
| 1600 | "need at most {} handles, got a sequence of length {}", |
| 1601 | max_total_objects, nhandles |
| 1602 | ))); |
| 1603 | } |
| 1604 | |
| 1605 | // Create batches of handles |
| 1606 | let batch_size = MAXIMUM_WAIT_OBJECTS - 1; // Leave room for cancel_event |
| 1607 | let mut batches: Vec<Vec<isize>> = Vec::new(); |
| 1608 | let mut i = 0; |
| 1609 | while i < nhandles { |
| 1610 | let end = core::cmp::min(i + batch_size, nhandles); |
| 1611 | batches.push(handles[i..end].to_vec()); |
| 1612 | i = end; |
| 1613 | } |
| 1614 | |
| 1615 | #[cfg(feature = "threading")] |
| 1616 | let sigint_event = { |
| 1617 | let is_main = crate::stdlib::_thread::get_ident() == vm.state.main_thread_ident.load(); |
| 1618 | if is_main { |
| 1619 | let handle = crate::signal::get_sigint_event().unwrap_or_else(|| { |
| 1620 | let handle = unsafe { WinCreateEventW(null(), 1, 0, null()) }; |
| 1621 | if !handle.is_null() { |
| 1622 | crate::signal::set_sigint_event(handle as isize); |
| 1623 | } |
nothing calls this directly
no test coverage detected