@@ -18,20 +18,56 @@ use crate::sys_common::IntoInner;
18
18
// Anonymous pipes
19
19
////////////////////////////////////////////////////////////////////////////////
20
20
21
- pub struct AnonPipe {
22
- inner : Handle ,
21
+ // A 64kb pipe capacity is the same as a typical Linux default.
22
+ const PIPE_BUFFER_CAPACITY : u32 = 64 * 1024 ;
23
+
24
+ pub enum AnonPipe {
25
+ Sync ( Handle ) ,
26
+ Async ( Handle ) ,
23
27
}
24
28
25
29
impl IntoInner < Handle > for AnonPipe {
26
30
fn into_inner ( self ) -> Handle {
27
- self . inner
31
+ match self {
32
+ Self :: Sync ( handle) => handle,
33
+ Self :: Async ( handle) => handle,
34
+ }
28
35
}
29
36
}
30
37
31
38
pub struct Pipes {
32
39
pub ours : AnonPipe ,
33
40
pub theirs : AnonPipe ,
34
41
}
42
+ impl Pipes {
43
+ /// Create a new pair of pipes where both pipes are synchronous.
44
+ ///
45
+ /// These must not be used asynchronously.
46
+ pub fn new_synchronous (
47
+ ours_readable : bool ,
48
+ their_handle_inheritable : bool ,
49
+ ) -> io:: Result < Self > {
50
+ unsafe {
51
+ // If `CreatePipe` succeeds, these will be our pipes.
52
+ let mut read = ptr:: null_mut ( ) ;
53
+ let mut write = ptr:: null_mut ( ) ;
54
+
55
+ if c:: CreatePipe ( & mut read, & mut write, ptr:: null ( ) , PIPE_BUFFER_CAPACITY ) == 0 {
56
+ Err ( io:: Error :: last_os_error ( ) )
57
+ } else {
58
+ let ( ours, theirs) = if ours_readable { ( read, write) } else { ( write, read) } ;
59
+ let ours = Handle :: from_raw_handle ( ours) ;
60
+ let theirs = Handle :: from_raw_handle ( theirs) ;
61
+
62
+ if their_handle_inheritable {
63
+ theirs. set_inheritable ( ) ?;
64
+ }
65
+
66
+ Ok ( Pipes { ours : AnonPipe :: Sync ( ours) , theirs : AnonPipe :: Sync ( theirs) } )
67
+ }
68
+ }
69
+ }
70
+ }
35
71
36
72
/// Although this looks similar to `anon_pipe` in the Unix module it's actually
37
73
/// subtly different. Here we'll return two pipes in the `Pipes` return value,
@@ -53,9 +89,6 @@ pub struct Pipes {
53
89
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
54
90
/// once at a time (which we do indeed guarantee).
55
91
pub fn anon_pipe ( ours_readable : bool , their_handle_inheritable : bool ) -> io:: Result < Pipes > {
56
- // A 64kb pipe capacity is the same as a typical Linux default.
57
- const PIPE_BUFFER_CAPACITY : u32 = 64 * 1024 ;
58
-
59
92
// Note that we specifically do *not* use `CreatePipe` here because
60
93
// unfortunately the anonymous pipes returned do not support overlapped
61
94
// operations. Instead, we create a "hopefully unique" name and create a
@@ -156,12 +189,9 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
156
189
} ;
157
190
opts. security_attributes ( & mut sa) ;
158
191
let theirs = File :: open ( Path :: new ( & name) , & opts) ?;
159
- let theirs = AnonPipe { inner : theirs. into_inner ( ) } ;
192
+ let theirs = AnonPipe :: Sync ( theirs. into_inner ( ) ) ;
160
193
161
- Ok ( Pipes {
162
- ours : AnonPipe { inner : ours } ,
163
- theirs : AnonPipe { inner : theirs. into_inner ( ) } ,
164
- } )
194
+ Ok ( Pipes { ours : AnonPipe :: Async ( ours) , theirs } )
165
195
}
166
196
}
167
197
@@ -171,12 +201,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
171
201
/// This is achieved by creating a new set of pipes and spawning a thread that
172
202
/// relays messages between the source and the synchronous pipe.
173
203
pub fn spawn_pipe_relay (
174
- source : & AnonPipe ,
204
+ source : & Handle ,
175
205
ours_readable : bool ,
176
206
their_handle_inheritable : bool ,
177
207
) -> io:: Result < AnonPipe > {
178
208
// We need this handle to live for the lifetime of the thread spawned below.
179
- let source = source. duplicate ( ) ? ;
209
+ let source = AnonPipe :: Async ( source. duplicate ( 0 , true , c :: DUPLICATE_SAME_ACCESS ) ? ) ;
180
210
181
211
// create a new pair of anon pipes.
182
212
let Pipes { theirs, ours } = anon_pipe ( ours_readable, their_handle_inheritable) ?;
@@ -227,19 +257,24 @@ type AlertableIoFn = unsafe extern "system" fn(
227
257
228
258
impl AnonPipe {
229
259
pub fn handle ( & self ) -> & Handle {
230
- & self . inner
260
+ match self {
261
+ Self :: Async ( ref handle) => handle,
262
+ Self :: Sync ( ref handle) => handle,
263
+ }
231
264
}
232
265
pub fn into_handle ( self ) -> Handle {
233
- self . inner
234
- }
235
- fn duplicate ( & self ) -> io:: Result < Self > {
236
- self . inner . duplicate ( 0 , false , c:: DUPLICATE_SAME_ACCESS ) . map ( |inner| AnonPipe { inner } )
266
+ self . into_inner ( )
237
267
}
238
268
239
269
pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
240
270
let result = unsafe {
241
271
let len = crate :: cmp:: min ( buf. len ( ) , c:: DWORD :: MAX as usize ) as c:: DWORD ;
242
- self . alertable_io_internal ( c:: ReadFileEx , buf. as_mut_ptr ( ) as _ , len)
272
+ match self {
273
+ Self :: Sync ( ref handle) => handle. read ( buf) ,
274
+ Self :: Async ( _) => {
275
+ self . alertable_io_internal ( c:: ReadFileEx , buf. as_mut_ptr ( ) as _ , len)
276
+ }
277
+ }
243
278
} ;
244
279
245
280
match result {
@@ -253,28 +288,33 @@ impl AnonPipe {
253
288
}
254
289
255
290
pub fn read_vectored ( & self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
256
- self . inner . read_vectored ( bufs)
291
+ io :: default_read_vectored ( |buf| self . read ( buf ) , bufs)
257
292
}
258
293
259
294
#[ inline]
260
295
pub fn is_read_vectored ( & self ) -> bool {
261
- self . inner . is_read_vectored ( )
296
+ false
262
297
}
263
298
264
299
pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
265
300
unsafe {
266
301
let len = crate :: cmp:: min ( buf. len ( ) , c:: DWORD :: MAX as usize ) as c:: DWORD ;
267
- self . alertable_io_internal ( c:: WriteFileEx , buf. as_ptr ( ) as _ , len)
302
+ match self {
303
+ Self :: Sync ( ref handle) => handle. write ( buf) ,
304
+ Self :: Async ( _) => {
305
+ self . alertable_io_internal ( c:: WriteFileEx , buf. as_ptr ( ) as _ , len)
306
+ }
307
+ }
268
308
}
269
309
}
270
310
271
311
pub fn write_vectored ( & self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
272
- self . inner . write_vectored ( bufs)
312
+ io :: default_write_vectored ( |buf| self . write ( buf ) , bufs)
273
313
}
274
314
275
315
#[ inline]
276
316
pub fn is_write_vectored ( & self ) -> bool {
277
- self . inner . is_write_vectored ( )
317
+ false
278
318
}
279
319
280
320
/// Synchronizes asynchronous reads or writes using our anonymous pipe.
@@ -346,7 +386,7 @@ impl AnonPipe {
346
386
347
387
// Asynchronous read of the pipe.
348
388
// If successful, `callback` will be called once it completes.
349
- let result = io ( self . inner . as_handle ( ) , buf, len, & mut overlapped, callback) ;
389
+ let result = io ( self . handle ( ) . as_handle ( ) , buf, len, & mut overlapped, callback) ;
350
390
if result == c:: FALSE {
351
391
// We can return here because the call failed.
352
392
// After this we must not return until the I/O completes.
0 commit comments