1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; 15 use std::time::Duration; 16 use std::{cmp, io}; 17 18 use super::Handle; 19 use crate::sys::winapi::{ 20 CreateIoCompletionPort, GetQueuedCompletionStatusEx, PostQueuedCompletionStatus, HANDLE, 21 INVALID_HANDLE_VALUE, OVERLAPPED, OVERLAPPED_ENTRY, 22 }; 23 use crate::sys::Overlapped; 24 use crate::{Event, Token}; 25 26 /// IOCP's HANDLE. 27 #[derive(Debug)] 28 pub(crate) struct CompletionPort { 29 handle: Handle, 30 } 31 32 impl CompletionPort { 33 /// Creates a new CompletionPort new() -> io::Result<CompletionPort>34 pub(crate) fn new() -> io::Result<CompletionPort> { 35 let handle = unsafe { CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0) }; 36 if handle == 0 { 37 Err(io::Error::last_os_error()) 38 } else { 39 Ok(CompletionPort { 40 handle: Handle::new(handle), 41 }) 42 } 43 } 44 /// Add t to CompletionPort add_handle<T: AsRawHandle + ?Sized>( &self, token: usize, t: &T, ) -> io::Result<()>45 pub(crate) fn add_handle<T: AsRawHandle + ?Sized>( 46 &self, 47 token: usize, 48 t: &T, 49 ) -> io::Result<()> { 50 syscall!( 51 CreateIoCompletionPort(t.as_raw_handle() as HANDLE, self.handle.raw(), token, 0), 52 () 53 ) 54 } 55 56 /// Gets the completed events in the IOCP, and can get multiple events at 57 /// the same time. Return the set of completed events get_results<'a>( &self, list: &'a mut [CompletionStatus], timeout: Option<Duration>, ) -> io::Result<&'a mut [CompletionStatus]>58 pub(crate) fn get_results<'a>( 59 &self, 60 list: &'a mut [CompletionStatus], 61 timeout: Option<Duration>, 62 ) -> io::Result<&'a mut [CompletionStatus]> { 63 let len = cmp::min(list.len(), u32::MAX as usize) as u32; 64 let mut removed = 0; 65 let timeout = match timeout { 66 Some(dur) => { 67 let dur_ms = (dur + Duration::from_nanos(999_999)).as_millis(); 68 cmp::min(dur_ms, u32::MAX as u128) as u32 69 } 70 None => u32::MAX, 71 }; 72 73 syscall!( 74 GetQueuedCompletionStatusEx( 75 self.handle.raw(), 76 list.as_ptr() as *mut _, 77 len, 78 &mut removed, 79 timeout, 80 0, 81 ), 82 &mut list[..removed as usize] 83 ) 84 } 85 86 /// Posts an I/O completion packet to an I/O completion port. post(&self, token: Token) -> io::Result<()>87 pub(crate) fn post(&self, token: Token) -> io::Result<()> { 88 let mut event = Event::new(token); 89 event.set_readable(); 90 91 let status = event.as_completion_status(); 92 syscall!( 93 PostQueuedCompletionStatus( 94 self.handle.raw(), 95 status.0.dwNumberOfBytesTransferred, 96 status.0.lpCompletionKey, 97 status.0.lpOverlapped 98 ), 99 () 100 ) 101 } 102 } 103 104 impl IntoRawHandle for CompletionPort { into_raw_handle(self) -> RawHandle105 fn into_raw_handle(self) -> RawHandle { 106 self.handle.into_raw() 107 } 108 } 109 110 /// Includes OVERLAPPED_ENTRY struct which contains operation result of IOCP 111 #[derive(Clone, Copy)] 112 pub struct CompletionStatus(OVERLAPPED_ENTRY); 113 114 unsafe impl Send for CompletionStatus {} 115 unsafe impl Sync for CompletionStatus {} 116 117 impl CompletionStatus { 118 /// Creates a new `CompletionStatus`. new(bytes: u32, token: usize, overlapped: *mut Overlapped) -> Self119 pub(crate) fn new(bytes: u32, token: usize, overlapped: *mut Overlapped) -> Self { 120 CompletionStatus(OVERLAPPED_ENTRY { 121 dwNumberOfBytesTransferred: bytes, 122 lpCompletionKey: token, 123 lpOverlapped: overlapped.cast::<_>(), 124 Internal: 0, 125 }) 126 } 127 128 /// Creates a CompletionStatus with 0. zero() -> Self129 pub fn zero() -> Self { 130 Self::new(0, 0, std::ptr::null_mut()) 131 } 132 133 /// Returns dwNumberOfBytesTransferred of OVERLAPPED_ENTRY. bytes_transferred(&self) -> u32134 pub fn bytes_transferred(&self) -> u32 { 135 self.0.dwNumberOfBytesTransferred 136 } 137 138 /// Returns lpCompletionKey of OVERLAPPED_ENTRY. token(&self) -> usize139 pub fn token(&self) -> usize { 140 self.0.lpCompletionKey 141 } 142 143 /// Returns lpOverlapped of OVERLAPPED_ENTRY. overlapped(&self) -> *mut OVERLAPPED144 pub fn overlapped(&self) -> *mut OVERLAPPED { 145 self.0.lpOverlapped 146 } 147 148 /// Returns OVERLAPPED_ENTRY struct. entry(&self) -> &OVERLAPPED_ENTRY149 pub fn entry(&self) -> &OVERLAPPED_ENTRY { 150 &self.0 151 } 152 } 153