/src/libstd/io/pipe.rs

https://github.com/sonwow/rust · Rust · 136 lines · 72 code · 18 blank · 46 comment · 4 complexity · d4eb4c2a14211f03176ea12ba8d22e7b MD5 · raw file

  1. // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. //! Synchronous, in-memory pipes.
  11. //!
  12. //! Currently these aren't particularly useful, there only exists bindings
  13. //! enough so that pipes can be created to child processes.
  14. #![allow(missing_docs)]
  15. use prelude::*;
  16. use io::IoResult;
  17. use libc;
  18. use sync::Arc;
  19. use sys_common;
  20. use sys;
  21. use sys::fs::FileDesc as FileDesc;
  22. /// A synchronous, in-memory pipe.
  23. pub struct PipeStream {
  24. inner: Arc<FileDesc>
  25. }
  26. pub struct PipePair {
  27. pub reader: PipeStream,
  28. pub writer: PipeStream,
  29. }
  30. impl PipeStream {
  31. /// Consumes a file descriptor to return a pipe stream that will have
  32. /// synchronous, but non-blocking reads/writes. This is useful if the file
  33. /// descriptor is acquired via means other than the standard methods.
  34. ///
  35. /// This operation consumes ownership of the file descriptor and it will be
  36. /// closed once the object is deallocated.
  37. ///
  38. /// # Example
  39. ///
  40. /// ```{rust,no_run}
  41. /// # #![allow(unused_must_use)]
  42. /// extern crate libc;
  43. ///
  44. /// use std::io::pipe::PipeStream;
  45. ///
  46. /// fn main() {
  47. /// let mut pipe = PipeStream::open(libc::STDERR_FILENO);
  48. /// pipe.write(b"Hello, stderr!");
  49. /// }
  50. /// ```
  51. pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
  52. Ok(PipeStream::from_filedesc(FileDesc::new(fd, true)))
  53. }
  54. // FIXME: expose this some other way
  55. /// Wrap a FileDesc directly, taking ownership.
  56. #[doc(hidden)]
  57. pub fn from_filedesc(fd: FileDesc) -> PipeStream {
  58. PipeStream { inner: Arc::new(fd) }
  59. }
  60. /// Creates a pair of in-memory OS pipes for a unidirectional communication
  61. /// stream.
  62. ///
  63. /// The structure returned contains a reader and writer I/O object. Data
  64. /// written to the writer can be read from the reader.
  65. ///
  66. /// # Errors
  67. ///
  68. /// This function can fail to succeed if the underlying OS has run out of
  69. /// available resources to allocate a new pipe.
  70. pub fn pair() -> IoResult<PipePair> {
  71. let (reader, writer) = try!(unsafe { sys::os::pipe() });
  72. Ok(PipePair {
  73. reader: PipeStream::from_filedesc(reader),
  74. writer: PipeStream::from_filedesc(writer),
  75. })
  76. }
  77. }
  78. impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
  79. fn as_inner(&self) -> &sys::fs::FileDesc {
  80. &*self.inner
  81. }
  82. }
  83. impl Clone for PipeStream {
  84. fn clone(&self) -> PipeStream {
  85. PipeStream { inner: self.inner.clone() }
  86. }
  87. }
  88. impl Reader for PipeStream {
  89. fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
  90. self.inner.read(buf)
  91. }
  92. }
  93. impl Writer for PipeStream {
  94. fn write(&mut self, buf: &[u8]) -> IoResult<()> {
  95. self.inner.write(buf)
  96. }
  97. }
  98. #[cfg(test)]
  99. mod test {
  100. use prelude::*;
  101. #[test]
  102. fn partial_read() {
  103. use os;
  104. use io::pipe::PipeStream;
  105. let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
  106. let out = PipeStream::open(writer);
  107. let mut input = PipeStream::open(reader);
  108. let (tx, rx) = channel();
  109. spawn(move|| {
  110. let mut out = out;
  111. out.write(&[10]).unwrap();
  112. rx.recv(); // don't close the pipe until the other read has finished
  113. });
  114. let mut buf = [0, ..10];
  115. input.read(&mut buf).unwrap();
  116. tx.send(());
  117. }
  118. }