Conflicts: src/doc/guide.md src/libcollections/bit.rs src/libcollections/btree/node.rs src/libcollections/slice.rs src/libcore/ops.rs src/libcore/prelude.rs src/librand/rand_impls.rs src/librustc/middle/check_match.rs src/librustc/middle/infer/region_inference/mod.rs src/librustc_driver/lib.rs src/librustdoc/test.rs src/libstd/bitflags.rs src/libstd/io/comm_adapters.rs src/libstd/io/mem.rs src/libstd/io/mod.rs src/libstd/io/net/pipe.rs src/libstd/io/net/tcp.rs src/libstd/io/net/udp.rs src/libstd/io/pipe.rs src/libstd/io/process.rs src/libstd/io/stdio.rs src/libstd/io/timer.rs src/libstd/io/util.rs src/libstd/macros.rs src/libstd/os.rs src/libstd/path/posix.rs src/libstd/path/windows.rs src/libstd/prelude/v1.rs src/libstd/rand/mod.rs src/libstd/rand/os.rs src/libstd/sync/barrier.rs src/libstd/sync/condvar.rs src/libstd/sync/future.rs src/libstd/sync/mpsc/mod.rs src/libstd/sync/mpsc/mpsc_queue.rs src/libstd/sync/mpsc/select.rs src/libstd/sync/mpsc/spsc_queue.rs src/libstd/sync/mutex.rs src/libstd/sync/once.rs src/libstd/sync/rwlock.rs src/libstd/sync/semaphore.rs src/libstd/sync/task_pool.rs src/libstd/sys/common/helper_thread.rs src/libstd/sys/unix/process.rs src/libstd/sys/unix/timer.rs src/libstd/sys/windows/c.rs src/libstd/sys/windows/timer.rs src/libstd/sys/windows/tty.rs src/libstd/thread.rs src/libstd/thread_local/mod.rs src/libstd/thread_local/scoped.rs src/libtest/lib.rs src/test/auxiliary/cci_capture_clause.rs src/test/bench/shootout-reverse-complement.rs src/test/bench/shootout-spectralnorm.rs src/test/compile-fail/array-old-syntax-2.rs src/test/compile-fail/bind-by-move-no-guards.rs src/test/compile-fail/builtin-superkinds-self-type.rs src/test/compile-fail/comm-not-freeze-receiver.rs src/test/compile-fail/comm-not-freeze.rs src/test/compile-fail/issue-12041.rs src/test/compile-fail/unsendable-class.rs src/test/run-pass/builtin-superkinds-capabilities-transitive.rs src/test/run-pass/builtin-superkinds-capabilities-xc.rs src/test/run-pass/builtin-superkinds-capabilities.rs src/test/run-pass/builtin-superkinds-self-type.rs src/test/run-pass/capturing-logging.rs src/test/run-pass/closure-bounds-can-capture-chan.rs src/test/run-pass/comm.rs src/test/run-pass/core-run-destroy.rs src/test/run-pass/drop-trait-enum.rs src/test/run-pass/hashmap-memory.rs src/test/run-pass/issue-13494.rs src/test/run-pass/issue-3609.rs src/test/run-pass/issue-4446.rs src/test/run-pass/issue-4448.rs src/test/run-pass/issue-8827.rs src/test/run-pass/issue-9396.rs src/test/run-pass/ivec-tag.rs src/test/run-pass/rust-log-filter.rs src/test/run-pass/send-resource.rs src/test/run-pass/send-type-inference.rs src/test/run-pass/sendable-class.rs src/test/run-pass/spawn-types.rs src/test/run-pass/task-comm-0.rs src/test/run-pass/task-comm-10.rs src/test/run-pass/task-comm-11.rs src/test/run-pass/task-comm-13.rs src/test/run-pass/task-comm-14.rs src/test/run-pass/task-comm-15.rs src/test/run-pass/task-comm-16.rs src/test/run-pass/task-comm-3.rs src/test/run-pass/task-comm-4.rs src/test/run-pass/task-comm-5.rs src/test/run-pass/task-comm-6.rs src/test/run-pass/task-comm-7.rs src/test/run-pass/task-comm-9.rs src/test/run-pass/task-comm-chan-nil.rs src/test/run-pass/task-spawn-move-and-copy.rs src/test/run-pass/task-stderr.rs src/test/run-pass/tcp-accept-stress.rs src/test/run-pass/tcp-connect-timeouts.rs src/test/run-pass/tempfile.rs src/test/run-pass/trait-bounds-in-arc.rs src/test/run-pass/trivial-message.rs src/test/run-pass/unique-send-2.rs src/test/run-pass/unique-send.rs src/test/run-pass/unwind-resource.rs
139 lines
3.8 KiB
Rust
139 lines
3.8 KiB
Rust
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! Synchronous, in-memory pipes.
|
|
//!
|
|
//! Currently these aren't particularly useful, there only exists bindings
|
|
//! enough so that pipes can be created to child processes.
|
|
|
|
#![allow(missing_docs)]
|
|
|
|
use prelude::v1::*;
|
|
|
|
use io::IoResult;
|
|
use libc;
|
|
use sync::Arc;
|
|
|
|
use sys_common;
|
|
use sys;
|
|
use sys::fs::FileDesc as FileDesc;
|
|
|
|
/// A synchronous, in-memory pipe.
|
|
pub struct PipeStream {
|
|
inner: Arc<FileDesc>
|
|
}
|
|
|
|
pub struct PipePair {
|
|
pub reader: PipeStream,
|
|
pub writer: PipeStream,
|
|
}
|
|
|
|
impl PipeStream {
|
|
/// Consumes a file descriptor to return a pipe stream that will have
|
|
/// synchronous, but non-blocking reads/writes. This is useful if the file
|
|
/// descriptor is acquired via means other than the standard methods.
|
|
///
|
|
/// This operation consumes ownership of the file descriptor and it will be
|
|
/// closed once the object is deallocated.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```{rust,no_run}
|
|
/// # #![allow(unused_must_use)]
|
|
/// extern crate libc;
|
|
///
|
|
/// use std::io::pipe::PipeStream;
|
|
///
|
|
/// fn main() {
|
|
/// let mut pipe = PipeStream::open(libc::STDERR_FILENO);
|
|
/// pipe.write(b"Hello, stderr!");
|
|
/// }
|
|
/// ```
|
|
pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
|
|
Ok(PipeStream::from_filedesc(FileDesc::new(fd, true)))
|
|
}
|
|
|
|
// FIXME: expose this some other way
|
|
/// Wrap a FileDesc directly, taking ownership.
|
|
#[doc(hidden)]
|
|
pub fn from_filedesc(fd: FileDesc) -> PipeStream {
|
|
PipeStream { inner: Arc::new(fd) }
|
|
}
|
|
|
|
/// Creates a pair of in-memory OS pipes for a unidirectional communication
|
|
/// stream.
|
|
///
|
|
/// The structure returned contains a reader and writer I/O object. Data
|
|
/// written to the writer can be read from the reader.
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// This function can fail to succeed if the underlying OS has run out of
|
|
/// available resources to allocate a new pipe.
|
|
pub fn pair() -> IoResult<PipePair> {
|
|
let (reader, writer) = try!(unsafe { sys::os::pipe() });
|
|
Ok(PipePair {
|
|
reader: PipeStream::from_filedesc(reader),
|
|
writer: PipeStream::from_filedesc(writer),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
|
|
fn as_inner(&self) -> &sys::fs::FileDesc {
|
|
&*self.inner
|
|
}
|
|
}
|
|
|
|
impl Clone for PipeStream {
|
|
fn clone(&self) -> PipeStream {
|
|
PipeStream { inner: self.inner.clone() }
|
|
}
|
|
}
|
|
|
|
impl Reader for PipeStream {
|
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
|
self.inner.read(buf)
|
|
}
|
|
}
|
|
|
|
impl Writer for PipeStream {
|
|
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
|
self.inner.write(buf)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use prelude::v1::*;
|
|
|
|
use sync::mpsc::channel;
|
|
use thread::Thread;
|
|
|
|
#[test]
|
|
fn partial_read() {
|
|
use os;
|
|
use io::pipe::PipeStream;
|
|
|
|
let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
|
|
let out = PipeStream::open(writer);
|
|
let mut input = PipeStream::open(reader);
|
|
let (tx, rx) = channel();
|
|
let _t = Thread::spawn(move|| {
|
|
let mut out = out;
|
|
out.write(&[10]).unwrap();
|
|
rx.recv().unwrap(); // don't close the pipe until the other read has finished
|
|
});
|
|
|
|
let mut buf = [0; 10];
|
|
input.read(&mut buf).unwrap();
|
|
tx.send(()).unwrap();
|
|
}
|
|
}
|