-
Notifications
You must be signed in to change notification settings - Fork 732
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add preliminary test for the new old Windows IOCP API
This is a first test to play with the Windows IOCP handler API.
- Loading branch information
1 parent
d8273f7
commit a5b18bc
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#![cfg(windows)] | ||
|
||
use std::ffi::OsStr; | ||
use std::ptr; | ||
use std::fs::File; | ||
use std::io::{self, Write, Seek, SeekFrom}; | ||
use std::os::windows::ffi::OsStrExt; | ||
use std::os::windows::io::{RawHandle, AsRawHandle, FromRawHandle}; | ||
use std::default::Default; | ||
use std::iter; | ||
use winapi::shared::winerror::ERROR_IO_PENDING; | ||
use winapi::um::{ | ||
fileapi::{CreateFileW, WriteFile, CREATE_ALWAYS}, | ||
errhandlingapi::GetLastError, | ||
winnt::GENERIC_WRITE, | ||
winbase::FILE_FLAG_OVERLAPPED, | ||
minwinbase::OVERLAPPED, | ||
handleapi::INVALID_HANDLE_VALUE, | ||
}; | ||
use mio::{Poll, Token, Interest, Events, event::Source, Registry}; | ||
use mio::windows; | ||
use winapi::um::minwinbase::OVERLAPPED_ENTRY; | ||
use mio::windows::Readiness; | ||
|
||
struct AsyncFile { | ||
file: File, | ||
binding: Option<windows::Binding> | ||
} | ||
|
||
impl Source for AsyncFile { | ||
fn register(&mut self, registry: &Registry, token: Token, _interests: Interest) -> io::Result<()> { | ||
let binding = windows::Binding::new(registry, token); | ||
self.binding = Some(binding); | ||
self.binding.as_ref().unwrap().register_handle(&self.file) | ||
} | ||
|
||
fn reregister(&mut self, _registry: &Registry, _token: Token, _interests: Interest) -> io::Result<()> { | ||
unimplemented!() | ||
} | ||
|
||
fn deregister(&mut self, _registry: &Registry) -> io::Result<()> { | ||
unimplemented!() | ||
} | ||
} | ||
|
||
impl AsRawHandle for AsyncFile { | ||
fn as_raw_handle(&self) -> RawHandle { | ||
self.file.as_raw_handle() | ||
} | ||
} | ||
|
||
#[test] | ||
fn register_custom_iocp_handler() { | ||
let mut poll = Poll::new().unwrap(); | ||
|
||
let path: &OsStr = "C:\\temp\\test.txt".as_ref(); | ||
let path_u16: Vec<u16> = path.encode_wide().chain(iter::once(0)).collect(); | ||
let mut file = unsafe { | ||
let handle = CreateFileW( | ||
path_u16.as_ptr(), | ||
GENERIC_WRITE, | ||
0, | ||
ptr::null_mut(), | ||
CREATE_ALWAYS, | ||
FILE_FLAG_OVERLAPPED, | ||
ptr::null_mut()); | ||
if handle == INVALID_HANDLE_VALUE { | ||
panic!("Unable to open file!"); | ||
} | ||
AsyncFile { | ||
file: File::from_raw_handle(handle), | ||
binding: None | ||
} | ||
}; | ||
|
||
poll.registry().register(&mut file, Token(0), Interest::WRITABLE).unwrap(); | ||
|
||
let mut buffer: Vec<_> = | ||
iter::successors(Some(15u8), |p| Some(p.wrapping_add(2))) | ||
.take(1024) | ||
.collect(); | ||
loop { | ||
unsafe { | ||
let mut overlapped = windows::Overlapped::new( | ||
move |_: &OVERLAPPED_ENTRY| Some(Readiness::WRITE)); | ||
if WriteFile(file.as_raw_handle(), buffer.as_mut_ptr() as *mut _, | ||
buffer.len() as u32, ptr::null_mut(), | ||
&mut overlapped as *mut windows::Overlapped as *mut OVERLAPPED) == 0 { | ||
match GetLastError() { | ||
ERROR_IO_PENDING => { | ||
let mut events = Events::with_capacity(16); | ||
poll.poll(&mut events, None).unwrap(); | ||
let mut event_iter = events.iter(); | ||
let event = event_iter.next().unwrap(); | ||
assert_eq!(0, event.token().0); | ||
assert!(event.is_writable()); | ||
assert!(event_iter.next().is_none()); | ||
break; | ||
}, | ||
|
||
e => panic!("Error during file write operation: {}", e) | ||
} | ||
} | ||
} | ||
} | ||
} |