ai-content-maker/.venv/Lib/site-packages/torch/include/c10/util/ExclusivelyOwned.h

141 lines
4.3 KiB
C++

#pragma once
#include <utility>
namespace c10 {
// See example implementation in TensorBase.h and TensorBody.h.
// Synopsis:
//
// repr_type -- type to use to store an owned T in ExclusivelyOwned.
//
// pointer_type -- pointer-esque type to return from
// ExclusivelyOwned's get() and operator*() methods.
//
// const_pointer_type -- similar to pointer_type, used for the const methods.
//
// static repr_type nullRepr() -- return a null instance of repr_type.
//
// template <class... Args>
// static repr_type createInPlace(Args&&... args) -- used by the in-place
// ExclusivelyOwned constructor.
//
// static repr_type moveToRepr(T&& x) -- move the given x into an
// instance of repr_type. used by the ExclusivelyOwned(T&&)
// constructor.
//
// static void destroyOwned(repr_type x) -- free memory for a
// known-exclusively-owned instance of x. Replaces calling repr_type's
// destructor. Being able to implement this more efficiently than
// repr_type's destructor is the main reason to use ExclusivelyOwned
// for a type.
//
// static T take(repr_type&) -- move out of the given repr_type into an owned T.
//
// static pointer_type getImpl(const repr_type&) -- return a pointer
// to the given repr_type. May take repr_type by value if that is more
// efficient.
template <typename T>
struct ExclusivelyOwnedTraits;
/// ExclusivelyOwned is a smart-pointer-like wrapper around an
/// exclusively-owned instance of some type T that normally has
/// mandatory reference counting (currently just Tensor). If you have
/// an isolated piece of code that knows that it has sole ownership of
/// an object of one of these types (i.e., because you created it
/// directly or using a factory function) and that object will not
/// escape from that isolated piece of code, then moving the object
/// into an ExclusivelyOwned will avoid an atomic reference count
/// decrement at destruction time.
///
/// If you directly create the Tensor in the first
/// place, you can use the in_place constructor of ExclusivelyOwned to
/// additionally avoid doing any stores to initialize the refcount &
/// weakcount.
template <typename T>
class ExclusivelyOwned {
using EOT = ExclusivelyOwnedTraits<T>;
typename ExclusivelyOwnedTraits<T>::repr_type repr_;
public:
ExclusivelyOwned() : repr_(EOT::nullRepr()) {}
explicit ExclusivelyOwned(T&& t) : repr_(EOT::moveToRepr(std::move(t))) {}
template <class... Args>
explicit ExclusivelyOwned(std::in_place_t, Args&&... args)
: repr_(EOT::createInPlace(std::forward<Args>(args)...)) {}
ExclusivelyOwned(const ExclusivelyOwned&) = delete;
ExclusivelyOwned(ExclusivelyOwned&& rhs) noexcept
: repr_(std::move(rhs.repr_)) {
rhs.repr_ = EOT::nullRepr();
}
ExclusivelyOwned& operator=(const ExclusivelyOwned&) = delete;
ExclusivelyOwned& operator=(ExclusivelyOwned&& rhs) noexcept {
EOT::destroyOwned(repr_);
repr_ = std::move(rhs.repr_);
rhs.repr_ = EOT::nullRepr();
return *this;
}
ExclusivelyOwned& operator=(T&& rhs) noexcept {
EOT::destroyOwned(repr_);
repr_ = EOT::moveToRepr(std::move(rhs));
return *this;
}
~ExclusivelyOwned() {
EOT::destroyOwned(repr_);
// Don't bother to call the destructor of repr_, since we already
// did specialized destruction for the exclusively-owned case in
// destroyOwned!
}
// We don't provide this because it would require us to be able to
// differentiate an owned-but-empty T from a lack of T. This is
// particularly problematic for Tensor, which wants to use an
// undefined Tensor as its null state.
explicit operator bool() const noexcept = delete;
operator T() && {
return take();
}
// NOTE: the equivalent operation on MaybeOwned is a moving
// operator*. For ExclusivelyOwned, take() and operator*() may well
// have different return types, so they are different functions.
T take() && {
return EOT::take(repr_);
}
typename EOT::const_pointer_type operator->() const {
return get();
}
typename EOT::const_pointer_type get() const {
return EOT::getImpl(repr_);
}
typename EOT::pointer_type operator->() {
return get();
}
typename EOT::pointer_type get() {
return EOT::getImpl(repr_);
}
std::remove_pointer_t<typename EOT::const_pointer_type>& operator*() const {
return *get();
}
std::remove_pointer_t<typename EOT::pointer_type>& operator*() {
return *get();
}
};
} // namespace c10