1 //===-- include/flang/Common/reference-counted.h ----------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_COMMON_REFERENCE_COUNTED_H_ 10 #define FORTRAN_COMMON_REFERENCE_COUNTED_H_ 11 12 // A class template of smart pointers to objects with their own 13 // reference counting object lifetimes that's lighter weight 14 // than std::shared_ptr<>. Not thread-safe. 15 16 namespace Fortran::common { 17 18 // A base class for reference-counted objects. Must be public. 19 template <typename A> class ReferenceCounted { 20 public: ReferenceCounted()21 ReferenceCounted() {} references()22 int references() const { return references_; } TakeReference()23 void TakeReference() { ++references_; } DropReference()24 void DropReference() { 25 if (--references_ == 0) { 26 delete static_cast<A *>(this); 27 } 28 } 29 30 private: 31 int references_{0}; 32 }; 33 34 // A reference to a reference-counted object. 35 template <typename A> class CountedReference { 36 public: 37 using type = A; CountedReference()38 CountedReference() {} CountedReference(type * m)39 CountedReference(type *m) : p_{m} { Take(); } CountedReference(const CountedReference & c)40 CountedReference(const CountedReference &c) : p_{c.p_} { Take(); } CountedReference(CountedReference && c)41 CountedReference(CountedReference &&c) : p_{c.p_} { c.p_ = nullptr; } 42 CountedReference &operator=(const CountedReference &c) { 43 c.Take(); 44 Drop(); 45 p_ = c.p_; 46 return *this; 47 } 48 CountedReference &operator=(CountedReference &&c) { 49 A *p{c.p_}; 50 c.p_ = nullptr; 51 Drop(); 52 p_ = p; 53 return *this; 54 } ~CountedReference()55 ~CountedReference() { Drop(); } 56 operator bool() const { return p_ != nullptr; } get()57 type *get() const { return p_; } 58 type &operator*() const { return *p_; } 59 type *operator->() const { return p_; } 60 61 private: Take()62 void Take() const { 63 if (p_) { 64 p_->TakeReference(); 65 } 66 } Drop()67 void Drop() { 68 if (p_) { 69 p_->DropReference(); 70 p_ = nullptr; 71 } 72 } 73 74 type *p_{nullptr}; 75 }; 76 } // namespace Fortran::common 77 #endif // FORTRAN_COMMON_REFERENCE_COUNTED_H_ 78