Skip to content

Commit e9eca7c

Browse files
committed
reference-counting analogy
1 parent 85e6e82 commit e9eca7c

File tree

1 file changed

+23
-20
lines changed

1 file changed

+23
-20
lines changed

library/std/src/io/mod.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -244,35 +244,37 @@
244244
//! means that file descriptors can be *exclusively owned*. (Here, "file descriptor" is meant to
245245
//! subsume similar concepts that exist across a wide range of operating systems even if they might
246246
//! use a different name, such as "handle".) An exclusively owned file descriptor is one that no
247-
//! other code is allowed to close, but the owner is allowed to close it any time. A type that owns
248-
//! its file descriptor should usually close it in its `drop` function. Types like [`File`] generally own
249-
//! their file descriptor. Similarly, file descriptors can be *borrowed*. This indicates that the
250-
//! file descriptor will not be closed for the lifetime of the borrow, but it does *not* imply any
251-
//! right to close this file descriptor, since it will likely be owned by someone else.
247+
//! other code is allowed to access in any way, but the owner is allowed to a access and even close
248+
//! it any time. A type that owns its file descriptor should usually close it in its `drop`
249+
//! function. Types like [`File`] generally own their file descriptor. Similarly, file descriptors
250+
//! can be *borrowed*, granting the temporary right to perform operations on this file descriptor.
251+
//! This indicates that the file descriptor will not be closed for the lifetime of the borrow, but
252+
//! it does *not* imply any right to close this file descriptor, since it will likely be owned by
253+
//! someone else.
252254
//!
253255
//! The platform-specific parts of the Rust standard library expose types that reflect these
254256
//! concepts, see [`os::unix`] and [`os::windows`].
255257
//!
256-
//! To uphold I/O safety, it is crucial that no code closes file descriptors it does not own. In
258+
//! To uphold I/O safety, it is crucial that no code acts on file descriptors it does not own. In
257259
//! other words, a safe function that takes a regular integer, treats it as a file descriptor, and
258-
//! closes it, is *unsound*.
260+
//! acts on it, is *unsound*.
259261
//!
260-
//! Not upholding I/O safety and closing a file descriptor without proof of ownership can lead to
262+
//! Not upholding I/O safety and acting on a file descriptor without proof of ownership can lead to
261263
//! misbehavior and even Undefined Behavior in code that relies on ownership of its file
262-
//! descriptors: the closed file descriptor could be re-allocated to some other library (such as the
263-
//! allocator or a memory mapping library) and now accessing the file descriptor will interfere in
264-
//! arbitrarily destructive ways with that other library.
264+
//! descriptors: a closed file descriptor could be re-allocated, so the original owner of that file
265+
//! descriptor is now working on the wrong file. Some code might even rely on fully encapsulating
266+
//! its file descriptors with no operations being performed by any other part of the program.
265267
//!
266268
//! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the
267269
//! underlying kernel object that the file descriptor references (also called "file description" on
268-
//! some operating systems). An owned file descriptor can have duplicates, i.e., other file
269-
//! descriptors that share the same kernel object. The exact rules around ownership of kernel
270-
//! objects are [still unclear](https://github.com/rust-lang/rust/issues/114167). Until that is
271-
//! clarified, the general advice is not to perform *any* operations on file descriptors that were
272-
//! never borrowed to or owned by you. In other words, receiving a borrowed file descriptor *does*
273-
//! give you the right to make a duplicate and use that duplicate beyond the end of the borrow, but
274-
//! nothing gives you the right to just `write` to a file descriptor that never even got borrowed to
275-
//! you.
270+
//! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned
271+
//! file descriptor, you cannot know whether there are any other file descriptors that reference the
272+
//! same kernel object. However, when you create a new kernel object, you know that you are holding
273+
//! the only reference to it. Just be careful not to borrow it to anyone, since they can obtain a
274+
//! clone and then you can no longer know what the reference count is! In that sense, [`OwnedFd`] is
275+
//! like `Arc` and [`BorrowedFd<'a>`] is like `&'a Arc` (and similar for the Windows types). There
276+
//! is no equivalent to `Box` for file descriptors in the standard library (that would be a type
277+
//! that guarantees that the reference count is `1`).
276278
//!
277279
//! [`File`]: crate::fs::File
278280
//! [`TcpStream`]: crate::net::TcpStream
@@ -284,7 +286,8 @@
284286
//! [`os::unix`]: ../os/unix/io/index.html
285287
//! [`os::windows`]: ../os/windows/io/index.html
286288
//! [`OwnedFd`]: ../os/fd/struct.OwnedFd.html
287-
//! [`BorrowedFd`]: ../os/fd/struct.BorrowedFd.html
289+
//! [`BorrowedFd<'a>`]: ../os/fd/struct.BorrowedFd.html
290+
//! [`Arc`]: crate::sync::Arc
288291
289292
#![stable(feature = "rust1", since = "1.0.0")]
290293

0 commit comments

Comments
 (0)