@@ -3,45 +3,27 @@ use std::sync::OnceLock;
33use std:: {
44 io,
55 os:: windows:: io:: { AsRawHandle , RawHandle } ,
6- sync:: atomic:: { AtomicUsize , Ordering } ,
76 time:: Duration ,
87} ;
98
10- use crossbeam_channel:: { unbounded, Receiver , RecvTimeoutError , Sender , TryRecvError } ;
11- use crossbeam_skiplist:: SkipMap ;
129#[ cfg( not( feature = "once_cell_try" ) ) ]
1310use once_cell:: sync:: OnceCell as OnceLock ;
14- use windows_sys:: Win32 :: {
15- Foundation :: ERROR_TIMEOUT ,
16- System :: IO :: { PostQueuedCompletionStatus , OVERLAPPED } ,
17- } ;
11+ use windows_sys:: Win32 :: System :: IO :: PostQueuedCompletionStatus ;
1812
1913use super :: CompletionPort ;
2014use crate :: { syscall, Entry , Overlapped , RawFd } ;
2115
2216struct GlobalPort {
2317 port : CompletionPort ,
24- drivers : SkipMap < usize , Sender < Entry > > ,
2518}
2619
2720impl GlobalPort {
2821 pub fn new ( ) -> io:: Result < Self > {
2922 Ok ( Self {
3023 port : CompletionPort :: new ( ) ?,
31- drivers : SkipMap :: new ( ) ,
3224 } )
3325 }
3426
35- pub fn register ( & self , driver : usize ) -> Receiver < Entry > {
36- let ( sender, receiver) = unbounded ( ) ;
37- self . drivers . insert ( driver, sender) ;
38- receiver
39- }
40-
41- pub fn deregister ( & self , driver : usize ) {
42- self . drivers . remove ( & driver) ;
43- }
44-
4527 pub fn attach ( & self , fd : RawFd ) -> io:: Result < ( ) > {
4628 self . port . attach ( fd)
4729 }
@@ -53,12 +35,6 @@ impl GlobalPort {
5335 ) -> io:: Result < ( ) > {
5436 self . port . post ( res, optr)
5537 }
56-
57- pub fn push ( & self , driver : usize , entry : Entry ) {
58- if let Some ( e) = self . drivers . get ( & driver) {
59- e. value ( ) . send ( entry) . ok ( ) ; // It's OK if the driver has been dropped.
60- }
61- }
6238}
6339
6440impl AsRawHandle for GlobalPort {
@@ -78,8 +54,20 @@ fn iocp_start() -> io::Result<()> {
7854 let port = iocp_port ( ) ?;
7955 std:: thread:: spawn ( move || {
8056 loop {
81- for ( driver, entry) in port. port . poll ( None , None ) ? {
82- port. push ( driver. 0 , entry) ;
57+ for entry in port. port . poll_raw ( None ) ? {
58+ // Any thin pointer is OK because we don't use the type of opcode.
59+ let overlapped_ptr: * mut Overlapped < ( ) > = entry. lpOverlapped . cast ( ) ;
60+ let overlapped = unsafe { & * overlapped_ptr } ;
61+ syscall ! (
62+ BOOL ,
63+ PostQueuedCompletionStatus (
64+ overlapped. driver,
65+ entry. dwNumberOfBytesTransferred,
66+ entry. lpCompletionKey,
67+ entry. lpOverlapped,
68+ )
69+ )
70+ . ok ( ) ;
8371 }
8472 }
8573 #[ allow( unreachable_code) ]
@@ -88,68 +76,39 @@ fn iocp_start() -> io::Result<()> {
8876 Ok ( ( ) )
8977}
9078
91- static DRIVER_COUNTER : AtomicUsize = AtomicUsize :: new ( 0 ) ;
9279static IOCP_INIT_ONCE : OnceLock < ( ) > = OnceLock :: new ( ) ;
9380
9481pub struct Port {
95- id : usize ,
96- port : & ' static GlobalPort ,
97- receiver : Receiver < Entry > ,
82+ port : CompletionPort ,
83+ global_port : & ' static GlobalPort ,
9884}
9985
10086impl Port {
10187 pub fn new ( ) -> io:: Result < Self > {
10288 IOCP_INIT_ONCE . get_or_try_init ( iocp_start) ?;
10389
104- let id = DRIVER_COUNTER . fetch_add ( 1 , Ordering :: AcqRel ) ;
105- let port = iocp_port ( ) ?;
106- let receiver = port. register ( id) ;
107- Ok ( Self { id, port, receiver } )
108- }
109-
110- pub fn id ( & self ) -> PortId {
111- PortId ( self . id )
90+ Ok ( Self {
91+ port : CompletionPort :: new ( ) ?,
92+ global_port : iocp_port ( ) ?,
93+ } )
11294 }
11395
11496 pub fn attach ( & mut self , fd : RawFd ) -> io:: Result < ( ) > {
115- self . port . attach ( fd)
97+ self . global_port . attach ( fd)
11698 }
11799
118100 pub fn handle ( & self ) -> PortHandle {
119- PortHandle :: new ( self . port )
101+ PortHandle :: new ( self . global_port )
120102 }
121103
122104 pub fn poll ( & self , timeout : Option < Duration > ) -> io:: Result < impl Iterator < Item = Entry > + ' _ > {
123- let e = if let Some ( timeout) = timeout {
124- match self . receiver . recv_timeout ( timeout) {
125- Ok ( e) => e,
126- Err ( e) => match e {
127- RecvTimeoutError :: Timeout => {
128- return Err ( io:: Error :: from_raw_os_error ( ERROR_TIMEOUT as _ ) ) ;
129- }
130- RecvTimeoutError :: Disconnected => {
131- unreachable ! ( "IOCP thread should not exit" )
132- }
133- } ,
134- }
135- } else {
136- self . receiver . recv ( ) . expect ( "IOCP thread should not exit" )
137- } ;
138- Ok ( Some ( e)
139- . into_iter ( )
140- . chain ( std:: iter:: from_fn ( || match self . receiver . try_recv ( ) {
141- Ok ( e) => Some ( e) ,
142- Err ( e) => match e {
143- TryRecvError :: Empty => None ,
144- TryRecvError :: Disconnected => unreachable ! ( "IOCP thread should not exit" ) ,
145- } ,
146- } ) ) )
105+ self . port . poll ( timeout, None )
147106 }
148107}
149108
150- impl Drop for Port {
151- fn drop ( & mut self ) {
152- self . port . deregister ( self . id ) ;
109+ impl AsRawHandle for Port {
110+ fn as_raw_handle ( & self ) -> RawHandle {
111+ self . port . as_raw_handle ( )
153112 }
154113}
155114
@@ -170,18 +129,3 @@ impl PortHandle {
170129 self . port . post ( res, optr)
171130 }
172131}
173-
174- /// The unique ID of IOCP driver.
175- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
176- pub struct PortId ( usize ) ;
177-
178- impl PortId {
179- /// Post raw entry to IOCP.
180- pub fn post_raw ( & self , transferred : u32 , key : usize , optr : * mut OVERLAPPED ) -> io:: Result < ( ) > {
181- syscall ! (
182- BOOL ,
183- PostQueuedCompletionStatus ( iocp_port( ) ?. as_raw_handle( ) as _, transferred, key, optr)
184- ) ?;
185- Ok ( ( ) )
186- }
187- }
0 commit comments