PageRenderTime 27ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/src/libstd/old_io/pipe.rs

https://gitlab.com/pranith/rust
Rust | 141 lines | 75 code | 19 blank | 47 comment | 4 complexity | 24029d6b88455edac512959e6b39d38d 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::v1::*;
  16. use old_io::{IoResult, Reader, Writer};
  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. /// # Examples
  39. ///
  40. /// ```{rust,no_run}
  41. /// # #![feature(old_io, libc, io)]
  42. /// # #![allow(unused_must_use)]
  43. /// extern crate libc;
  44. ///
  45. /// use std::old_io::*;
  46. ///
  47. /// fn main() {
  48. /// let mut pipe = PipeStream::open(libc::STDERR_FILENO);
  49. /// pipe.write(b"Hello, stderr!");
  50. /// }
  51. /// ```
  52. pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
  53. Ok(PipeStream::from_filedesc(FileDesc::new(fd, true)))
  54. }
  55. // FIXME: expose this some other way
  56. /// Wrap a FileDesc directly, taking ownership.
  57. #[doc(hidden)]
  58. pub fn from_filedesc(fd: FileDesc) -> PipeStream {
  59. PipeStream { inner: Arc::new(fd) }
  60. }
  61. /// Creates a pair of in-memory OS pipes for a unidirectional communication
  62. /// stream.
  63. ///
  64. /// The structure returned contains a reader and writer I/O object. Data
  65. /// written to the writer can be read from the reader.
  66. ///
  67. /// # Errors
  68. ///
  69. /// This function can fail to succeed if the underlying OS has run out of
  70. /// available resources to allocate a new pipe.
  71. pub fn pair() -> IoResult<PipePair> {
  72. let (reader, writer) = try!(unsafe { sys::os::pipe() });
  73. Ok(PipePair {
  74. reader: PipeStream::from_filedesc(reader),
  75. writer: PipeStream::from_filedesc(writer),
  76. })
  77. }
  78. }
  79. impl sys_common::AsInner<sys::fs::FileDesc> for PipeStream {
  80. fn as_inner(&self) -> &sys::fs::FileDesc {
  81. &*self.inner
  82. }
  83. }
  84. impl Clone for PipeStream {
  85. fn clone(&self) -> PipeStream {
  86. PipeStream { inner: self.inner.clone() }
  87. }
  88. }
  89. impl Reader for PipeStream {
  90. fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
  91. self.inner.read(buf)
  92. }
  93. }
  94. impl Writer for PipeStream {
  95. fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
  96. self.inner.write(buf)
  97. }
  98. }
  99. #[cfg(test)]
  100. mod test {
  101. use prelude::v1::*;
  102. use old_io::{Writer, Reader};
  103. use sync::mpsc::channel;
  104. use thread;
  105. #[test]
  106. fn partial_read() {
  107. use os;
  108. use old_io::pipe::PipeStream;
  109. let (reader, writer) = unsafe { ::sys::os::pipe().unwrap() };
  110. let out = PipeStream::open(writer.unwrap());
  111. let mut input = PipeStream::open(reader.unwrap());
  112. let (tx, rx) = channel();
  113. let _t = thread::spawn(move|| {
  114. let mut out = out;
  115. out.write(&[10]).unwrap();
  116. rx.recv().unwrap(); // don't close the pipe until the other read has finished
  117. });
  118. let mut buf = [0; 10];
  119. input.read(&mut buf).unwrap();
  120. tx.send(()).unwrap();
  121. }
  122. }