3 #include <c10/util/C++17.h> 4 #include <c10/util/Exception.h> 58 mutable std::atomic<size_t> refcount_;
59 mutable std::atomic<size_t> weakcount_;
61 template <
typename T,
typename NullType>
63 template <
typename T,
typename NullType>
76 # pragma warning(push) 77 # pragma warning(disable: 4297) // function assumed not to throw an exception but does 79 # pragma GCC diagnostic push 80 # pragma GCC diagnostic ignored "-Wpragmas" 81 # pragma GCC diagnostic ignored "-Wunknown-warning-option" 82 # pragma GCC diagnostic ignored "-Wterminate" 83 # pragma GCC diagnostic ignored "-Wexceptions" 86 refcount_.load() == 0,
87 "Tried to destruct an intrusive_ptr_target that still has intrusive_ptr to it");
89 weakcount_.load() == 0,
90 "Tried to destruct an intrusive_ptr_target that still has weak_intrusive_ptr to it");
94 # pragma GCC diagnostic pop 122 virtual void release_resources() {}
126 template <
class TTarget>
128 static constexpr TTarget* singleton() noexcept {
133 template<
class TTarget,
class ToNullType,
class FromNullType>
134 TTarget* assign_ptr_(TTarget* rhs) {
135 if (FromNullType::singleton() == rhs) {
136 return ToNullType::singleton();
143 template <
class TTarget,
class NullType>
161 NullType::singleton() == NullType::singleton(),
162 "NullType must have a constexpr singleton() method");
165 std::is_same<TTarget*, decltype(NullType::singleton())>::value,
166 "NullType::singleton() must return a element_type* pointer");
170 template <
class TTarget2,
class NullType2>
175 if (target_ != NullType::singleton()) {
176 size_t new_refcount = ++target_->refcount_;
179 "intrusive_ptr: Cannot increase refcount after it reached zero.");
183 void reset_() noexcept {
184 if (target_ != NullType::singleton() && --target_->refcount_ == 0) {
188 auto weak_count = --target_->weakcount_;
191 const_cast<c10::guts::remove_const_t<TTarget>*
>(target_)->release_resources();
192 if (weak_count == 0) {
196 target_ = NullType::singleton();
203 explicit intrusive_ptr(TTarget* target) noexcept : target_(target) {}
206 using element_type = TTarget;
211 rhs.target_ = NullType::singleton();
214 template <
class From,
class FromNullType>
216 : target_(detail::assign_ptr_<TTarget, NullType, FromNullType>(rhs.target_)) {
218 std::is_convertible<From*, TTarget*>::value,
219 "Type mismatch. intrusive_ptr move constructor got pointer of wrong type.");
220 rhs.target_ = FromNullType::singleton();
227 template <
class From,
class FromNullType>
230 : target_(detail::assign_ptr_<TTarget, NullType, FromNullType>(rhs.target_)) {
232 std::is_convertible<From*, TTarget*>::value,
233 "Type mismatch. intrusive_ptr copy constructor got pointer of wrong type.");
242 return operator=<TTarget, NullType>(std::move(rhs));
245 template <
class From,
class FromNullType>
249 std::is_convertible<From*, TTarget*>::value,
250 "Type mismatch. intrusive_ptr move assignment got pointer of wrong type.");
257 return operator=<TTarget, NullType>(rhs);
260 template <
class From,
class FromNullType>
263 std::is_convertible<From*, TTarget*>::value,
264 "Type mismatch. intrusive_ptr copy assignment got pointer of wrong type.");
270 TTarget*
get()
const noexcept {
274 const TTarget& operator*()
const noexcept {
278 TTarget& operator*() noexcept {
282 const TTarget* operator->()
const noexcept {
286 TTarget* operator->() noexcept {
290 operator bool()
const noexcept {
291 return target_ != NullType::singleton();
294 void reset() noexcept {
299 TTarget* tmp = target_;
300 target_ = rhs.target_;
305 bool defined()
const noexcept {
306 return target_ != NullType::singleton();
309 size_t use_count()
const noexcept {
310 if (target_ == NullType::singleton()) {
313 return target_->refcount_.load();
316 size_t weak_use_count()
const noexcept {
317 if (target_ == NullType::singleton()) {
320 return target_->weakcount_.load();
323 bool unique()
const noexcept {
324 return use_count() == 1;
335 TTarget* result = target_;
336 target_ = NullType::singleton();
349 owning_ptr == NullType::singleton() || owning_ptr->refcount_.load() > 0,
350 "intrusive_ptr: Can only intrusive_ptr::reclaim() owning pointers that were created using intrusive_ptr::release().");
354 template <
class... Args>
356 auto result =
intrusive_ptr(
new TTarget(std::forward<Args>(args)...));
360 ++result.target_->refcount_;
361 ++result.target_->weakcount_;
374 raw_ptr == NullType::singleton() || raw_ptr->refcount_.load() > 0,
375 "intrusive_ptr: Can only reclaim pointers that are owned by someone");
376 auto ptr = reclaim(raw_ptr);
390 template <
class TTarget,
class NullType>
398 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
399 inline bool operator<(
402 return lhs.get() < rhs.get();
405 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
406 inline bool operator==(
409 return lhs.get() == rhs.get();
412 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
413 inline bool operator!=(
416 return !operator==(lhs, rhs);
425 std::is_base_of<intrusive_ptr_target, TTarget>::value,
426 "intrusive_ptr can only be used for classes that inherit from intrusive_ptr_target.");
431 NullType::singleton() == NullType::singleton(),
432 "NullType must have a constexpr singleton() method");
435 std::is_same<TTarget*, decltype(NullType::singleton())>::value,
436 "NullType::singleton() must return a element_type* pointer");
440 template <
class TTarget2,
class NullType2>
444 if (target_ != NullType::singleton()) {
445 size_t new_weakcount = ++target_->weakcount_;
448 "weak_intrusive_ptr: Cannot increase weakcount after it reached zero.");
452 void reset_() noexcept {
453 if (target_ != NullType::singleton() && --target_->weakcount_ == 0) {
456 target_ = NullType::singleton();
465 : weak_intrusive_ptr(ptr.get()) {
469 weak_intrusive_ptr(weak_intrusive_ptr&& rhs) noexcept : target_(rhs.target_) {
470 rhs.target_ = NullType::singleton();
473 template <
class From,
class FromNullType>
476 : target_(detail::assign_ptr_<TTarget, NullType, FromNullType>(rhs.target_)) {
478 std::is_convertible<From*, TTarget*>::value,
479 "Type mismatch. weak_intrusive_ptr move constructor got pointer of wrong type.");
480 rhs.target_ = FromNullType::singleton();
483 weak_intrusive_ptr(
const weak_intrusive_ptr& rhs)
484 : target_(rhs.target_) {
488 template <
class From,
class FromNullType>
491 : target_(detail::assign_ptr_<TTarget, NullType, FromNullType>(rhs.target_)) {
493 std::is_convertible<From*, TTarget*>::value,
494 "Type mismatch. weak_intrusive_ptr copy constructor got pointer of wrong type.");
498 ~weak_intrusive_ptr() noexcept {
502 weak_intrusive_ptr& operator=(weak_intrusive_ptr&& rhs) & noexcept {
503 return operator=<TTarget, NullType>(std::move(rhs));
506 template <
class From,
class FromNullType>
507 weak_intrusive_ptr& operator=(
511 std::is_convertible<From*, TTarget*>::value,
512 "Type mismatch. weak_intrusive_ptr move assignment got pointer of wrong type.");
513 weak_intrusive_ptr tmp = std::move(rhs);
518 weak_intrusive_ptr& operator=(
const weak_intrusive_ptr& rhs) & noexcept {
519 return operator=<TTarget, NullType>(rhs);
522 template <
class From,
class FromNullType>
523 weak_intrusive_ptr& operator=(
526 std::is_convertible<From*, TTarget*>::value,
527 "Type mismatch. weak_intrusive_ptr copy assignment got pointer of wrong type.");
528 weak_intrusive_ptr tmp = rhs;
533 void reset() noexcept {
537 void swap(weak_intrusive_ptr& rhs) noexcept {
538 TTarget* tmp = target_;
539 target_ = rhs.target_;
564 TTarget* _unsafe_get_target()
const noexcept {
568 size_t use_count()
const noexcept {
569 if (target_ == NullType::singleton()) {
572 return target_->refcount_.load();
575 size_t weak_use_count()
const noexcept {
576 if (target_ == NullType::singleton()) {
579 return target_->weakcount_.load();
582 bool expired()
const noexcept {
583 return use_count() == 0;
587 auto refcount = target_->refcount_.load();
594 }
while (!target_->refcount_.compare_exchange_weak(refcount, refcount + 1));
607 TTarget* result = target_;
608 target_ = NullType::singleton();
619 static weak_intrusive_ptr
reclaim(TTarget* owning_weak_ptr) {
625 owning_weak_ptr == NullType::singleton() ||
626 owning_weak_ptr->weakcount_.load() > 1 ||
627 (owning_weak_ptr->refcount_.load() == 0 &&
628 owning_weak_ptr->weakcount_.load() > 0),
629 "weak_intrusive_ptr: Can only weak_intrusive_ptr::reclaim() owning pointers that were created using weak_intrusive_ptr::release().");
630 return weak_intrusive_ptr(owning_weak_ptr);
633 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
634 friend bool operator<(
637 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
638 friend bool operator==(
643 template <
class TTarget,
class NullType>
651 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
652 inline bool operator<(
655 return lhs.target_ < rhs.target_;
658 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
659 inline bool operator==(
662 return lhs.target_ == rhs.target_;
665 template <
class TTarget1,
class NullType1,
class TTarget2,
class NullType2>
666 inline bool operator!=(
669 return !operator==(lhs, rhs);
710 template <
typename T>
711 inline T* make_weak(
T*
self) {
721 auto r = ptr.use_count();
732 auto wptr_copy = wptr;
744 template <
typename T>
745 inline T* lock(
T*
self) {
747 auto ptr = wptr.lock();
749 return ptr.release();
755 auto r = wptr.use_count();
769 template <
class TTarget,
class NullType>
770 struct hash<
c10::intrusive_ptr<TTarget, NullType>> {
772 return std::hash<TTarget*>()(x.get());
775 template <
class TTarget,
class NullType>
776 struct hash<
c10::weak_intrusive_ptr<TTarget, NullType>> {
778 return std::hash<TTarget*>()(x._unsafe_get_target());
The low-level representation of a tensor, which contains a pointer to a storage (which contains the a...
static weak_intrusive_ptr reclaim(TTarget *owning_weak_ptr)
Takes an owning (but must be weakly referenced) pointer to TTarget* and creates a weak_intrusive_ptr ...
intrusive_ptr<T> is an alternative to shared_ptr<T> that has better performance because it does the r...
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
TTarget * release() noexcept
Returns an owning (!) pointer to the underlying object and makes the intrusive_ptr instance invalid...
TTarget * release() noexcept
Returns an owning (but still only weakly referenced) pointer to the underlying object and makes the w...
static intrusive_ptr reclaim(TTarget *owning_ptr)
Takes an owning pointer to TTarget* and creates an intrusive_ptr that takes over ownership.
static intrusive_ptr unsafe_reclaim_from_nonowning(TTarget *raw_ptr)
Turn a non-owning raw pointer to an intrusive_ptr.