MaybeOwned page for dev wiki (#63450)
authorBasil Hosmer <bhosmer@fb.com>
Wed, 18 Aug 2021 19:06:53 +0000 (12:06 -0700)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Wed, 18 Aug 2021 19:08:58 +0000 (12:08 -0700)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/63450

Brief guide to understanding `MaybeOwned<Tensor>`, aimed at C++ PT devs who are obliged to interact with existing uses of it, rather than encouraging new usage.

For reviewers: I haven't yet added a link to this page from anywhere. I'm thinking the right place is the [dev wiki main page C++ section](https://github.com/pytorch/pytorch/wiki#c) but happy to put it wherever makes sense, suggestions welcome.

Test Plan: Imported from OSS

Reviewed By: navahgar

Differential Revision: D30402313

Pulled By: bhosmer

fbshipit-source-id: 69b15909ecafcd8d88e44f664f88c3ad4eb26d84

docs/cpp/source/notes/maybe_owned.rst [new file with mode: 0644]

diff --git a/docs/cpp/source/notes/maybe_owned.rst b/docs/cpp/source/notes/maybe_owned.rst
new file mode 100644 (file)
index 0000000..8fa05f1
--- /dev/null
@@ -0,0 +1,59 @@
+MaybeOwned<Tensor>
+==================
+
+``MaybeOwned<Tensor>`` is a C++ smart pointer class that dynamically
+encodes whether a Tensor is *owned* or *borrowed*. It is used in
+certain performance-sensitive situations to avoid unnecessarily
+incrementing a Tensor’s reference count (at a small cost in
+overhead from the extra indirection).
+
+.. warning::
+    MaybeOwned must be used with **extreme** care. Claims of (non-)ownership
+    are not statically checked, and mistakes can cause reference undercounting
+    and use-after-free crashes.
+
+    Due to this lack of safety net, we discourage the use of MaybeOwned
+    outside code paths that are known to be highly performance sensitive.
+    However, if you encounter pre-existing uses of MaybeOwned in code that
+    you want to modify, it’s critical to understand how to use it correctly.
+
+The primary use case for ``MaybeOwned<Tensor>`` is a function or method that
+dynamically chooses between returning one of its arguments (typically
+from a passthrough or “no-op” code path) and returning a freshly constructed
+Tensor. Such a function would return a ``MaybeOwned<Tensor>`` in both cases,
+the former in a "borrowed" state via a call to ``MaybeOwned<Tensor>::borrowed()``,
+and the latter in an "owned" state via a call to ``MaybeOwned<Tensor>::owned()``.
+
+The canonical example is ``Tensor``'s ``expect_contiguous`` method, which shortcuts
+and returns a borrowed self-reference when already contiguous:
+
+.. code-block:: cpp
+
+  inline c10::MaybeOwned<Tensor> Tensor::expect_contiguous(MemoryFormat memory_format) const & {
+    if (is_contiguous(memory_format)) {
+      return c10::MaybeOwned<Tensor>::borrowed(*this);
+    } else {
+      return c10::MaybeOwned<Tensor>::owned(__dispatch_contiguous(memory_format));
+    }
+  }
+
+Using the vocabulary of lifetimes, the essential safety requirement for borrowing
+is that a borrowed Tensor must outlive any borrowing references to it. Here, for
+example, we can safely borrow ``*this``, but the Tensor returned by
+``__dispatch_contiguous()`` is freshly created, and borrowing a reference would
+effectively leave it ownerless.
+
+So, general rules of thumb:
+
+- When in doubt, don’t use ``MaybeOwned<Tensor>`` at all - in particular, prefer
+  avoiding using it in code that doesn’t use it already. New usage should only be
+  introduced when critical (and demonstrable) performance gains result.
+
+- When modifying or calling code that already uses ``MaybeOwned<Tensor>``, remember
+  that it's always safe to produce a ``MaybeOwned<Tensor>`` from a Tensor in hand
+  via a call to ``MaybeOwned<Tensor>::owned()``. This may result in an unnecessary
+  reference count, but never in misbehavior - so it's always the safer bet, unless
+  the lifetime of the Tensor you're looking to wrap is crystal clear.
+
+More details and implementation code can be found at <https://github.com/pytorch/pytorch/blob/master/c10/util/MaybeOwned.h> and
+<https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/templates/TensorBody.h>.