PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/libstd/io/pipe.rs

https://gitlab.com/skv-headless/test-submodules
Rust | 140 lines | 77 code | 18 blank | 45 comment | 6 complexity | 7366563d63aa8a9ffdd8d7908b3c2bc2 MD5 | raw file
Possible License(s): JSON, MIT
  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_doc)]
  15. use prelude::*;
  16. use io::{IoResult, IoError};
  17. use libc;
  18. use os;
  19. use boxed::Box;
  20. use rt::rtio::{RtioPipe, LocalIo};
  21. /// A synchronous, in-memory pipe.
  22. pub struct PipeStream {
  23. /// The internal, opaque runtime pipe object.
  24. obj: Box<RtioPipe + Send>,
  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
  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. LocalIo::maybe_raise(|io| {
  53. io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
  54. }).map_err(IoError::from_rtio_error)
  55. }
  56. #[doc(hidden)]
  57. pub fn new(inner: Box<RtioPipe + Send>) -> PipeStream {
  58. PipeStream { obj: inner }
  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. struct Closer { fd: libc::c_int }
  72. let os::Pipe { reader, writer } = try!(unsafe { os::pipe() });
  73. let mut reader = Closer { fd: reader };
  74. let mut writer = Closer { fd: writer };
  75. let io_reader = try!(PipeStream::open(reader.fd));
  76. reader.fd = -1;
  77. let io_writer = try!(PipeStream::open(writer.fd));
  78. writer.fd = -1;
  79. return Ok(PipePair { reader: io_reader, writer: io_writer });
  80. impl Drop for Closer {
  81. fn drop(&mut self) {
  82. if self.fd != -1 {
  83. let _ = unsafe { libc::close(self.fd) };
  84. }
  85. }
  86. }
  87. }
  88. }
  89. impl Clone for PipeStream {
  90. fn clone(&self) -> PipeStream {
  91. PipeStream { obj: self.obj.clone() }
  92. }
  93. }
  94. impl Reader for PipeStream {
  95. fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
  96. self.obj.read(buf).map_err(IoError::from_rtio_error)
  97. }
  98. }
  99. impl Writer for PipeStream {
  100. fn write(&mut self, buf: &[u8]) -> IoResult<()> {
  101. self.obj.write(buf).map_err(IoError::from_rtio_error)
  102. }
  103. }
  104. #[cfg(test)]
  105. mod test {
  106. iotest!(fn partial_read() {
  107. use os;
  108. use io::pipe::PipeStream;
  109. let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
  110. let out = PipeStream::open(writer);
  111. let mut input = PipeStream::open(reader);
  112. let (tx, rx) = channel();
  113. spawn(proc() {
  114. let mut out = out;
  115. out.write([10]).unwrap();
  116. rx.recv(); // don't close the pipe until the other read has finished
  117. });
  118. let mut buf = [0, ..10];
  119. input.read(buf).unwrap();
  120. tx.send(());
  121. })
  122. }