xgboost

intrusive_ptr.h
Go to the documentation of this file.
1
6 #ifndef XGBOOST_INTRUSIVE_PTR_H_
7 #define XGBOOST_INTRUSIVE_PTR_H_
8
9 #include <atomic>
10 #include <cinttypes>
11 #include <functional>
12 #include <ostream>
13
14 namespace xgboost {
20 class IntrusivePtrCell {
21 private:
22 std::atomic<int32_t> count_ {0};
23 template <typename T> friend class IntrusivePtr;
24
25 std::int32_t IncRef() noexcept {
26 return count_.fetch_add(1, std::memory_order_relaxed);
27 }
28 std::int32_t DecRef() noexcept {
29 return count_.fetch_sub(1, std::memory_order_release);
30 }
31 bool IsZero() const { return Count() == 0; }
32
33 public:
34 IntrusivePtrCell() noexcept = default;
35 int32_t Count() const { return count_.load(std::memory_order_relaxed); }
36 };
37
41 template <typename T> IntrusivePtrCell &IntrusivePtrRefCount(T const *ptr) noexcept;
42
73 template <typename T> class IntrusivePtr {
74 private:
75 void IncRef(T *ptr) {
76 if (ptr) {
77 IntrusivePtrRefCount(ptr).IncRef();
78 }
79 }
80 void DecRef(T *ptr) {
81 if (ptr) {
82 if (IntrusivePtrRefCount(ptr).DecRef() == 1) {
83 std::atomic_thread_fence(std::memory_order_acquire);
84 delete ptr;
85 }
86 }
87 }
88
89 protected:
90 T *ptr_{nullptr};
91
92 public:
93 using element_type = T; // NOLINT
94 struct Hash {
95 std::size_t operator()(IntrusivePtr<element_type> const &ptr) const noexcept {
96 return std::hash<element_type *>()(ptr.get());
97 }
98 };
104 explicit IntrusivePtr(T *p) : ptr_{p} {
105 if (ptr_) {
106 IncRef(ptr_);
107 }
108 }
109
110 IntrusivePtr() noexcept = default;
111 IntrusivePtr(IntrusivePtr const &that) : ptr_{that.ptr_} { IncRef(ptr_); }
112 IntrusivePtr(IntrusivePtr &&that) noexcept : ptr_{that.ptr_} { that.ptr_ = nullptr; }
113
114 ~IntrusivePtr() { DecRef(ptr_); }
115
116 IntrusivePtr<T> &operator=(IntrusivePtr<T> const &that) {
117 IntrusivePtr<T>{that}.swap(*this);
118 return *this;
119 }
120 IntrusivePtr<T> &operator=(IntrusivePtr<T> &&that) noexcept {
121 std::swap(ptr_, that.ptr_);
122 return *this;
123 }
124
125 void reset() { // NOLINT
126 DecRef(ptr_);
127 ptr_ = nullptr;
128 }
129 void reset(element_type *that) { IntrusivePtr{that}.swap(*this); } // NOLINT
130 // clang-tidy might manufacture a null value, disable the check
131 element_type &operator*() const noexcept { return *ptr_; } // NOLINT
132 element_type *operator->() const noexcept { return ptr_; }
133 element_type *get() const noexcept { return ptr_; } // NOLINT
134
135 explicit operator bool() const noexcept { return static_cast<bool>(ptr_); }
136
137 int32_t use_count() noexcept { // NOLINT
138 return ptr_ ? IntrusivePtrRefCount(ptr_).Count() : 0;
139 }
140
141 /*
142 * \brief Helper function for swapping 2 pointers.
143 */
144 void swap(IntrusivePtr<T> &that) noexcept { // NOLINT
145 std::swap(ptr_, that.ptr_);
146 }
147 };
148
149 template <class T, class U>
150 bool operator==(IntrusivePtr<T> const &x, IntrusivePtr<U> const &y) noexcept {
151 return x.get() == y.get();
152 }
153
154 template <class T, class U>
155 bool operator!=(IntrusivePtr<T> const &x, IntrusivePtr<U> const &y) noexcept {
156 return x.get() != y.get();
157 }
158
159 template <class T, class U>
160 bool operator==(IntrusivePtr<T> const &x, U *y) noexcept {
161 return x.get() == y;
162 }
163
164 template <class T, class U>
165 bool operator!=(IntrusivePtr<T> const &x, U *y) noexcept {
166 return x.get() != y;
167 }
168
169 template <class T, class U>
170 bool operator==(T *x, IntrusivePtr<U> const &y) noexcept {
171 return y == x;
172 }
173
174 template <class T, class U>
175 bool operator!=(T *x, IntrusivePtr<U> const &y) noexcept {
176 return y != x;
177 }
178
179 template <class T>
180 bool operator<(IntrusivePtr<T> const &x, IntrusivePtr<T> const &y) noexcept {
181 return std::less<T*>{}(x.get(), y.get());
182 }
183
184 template <class T>
185 bool operator<=(IntrusivePtr<T> const &x, IntrusivePtr<T> const &y) noexcept {
186 return std::less_equal<T*>{}(x.get(), y.get());
187 }
188
189 template <class T>
190 bool operator>(IntrusivePtr<T> const &x, IntrusivePtr<T> const &y) noexcept {
191 return !(x <= y);
192 }
193
194 template <class T>
195 bool operator>=(IntrusivePtr<T> const &x, IntrusivePtr<T> const &y) noexcept {
196 return !(x < y);
197 }
198
199 template <class E, class T, class Y>
200 std::basic_ostream<E, T> &operator<<(std::basic_ostream<E, T> &os,
201 IntrusivePtr<Y> const &p) {
202 os << p.get();
203 return os;
204 }
205 } // namespace xgboost
206
207 namespace std {
208 template <class T>
209 void swap(xgboost::IntrusivePtr<T> &x, // NOLINT
210 xgboost::IntrusivePtr<T> &y) noexcept {
211 x.swap(y);
212 }
213
214 template <typename T>
215 struct hash<xgboost::IntrusivePtr<T>> : public xgboost::IntrusivePtr<T>::Hash {};
216 } // namespace std
217 #endif // XGBOOST_INTRUSIVE_PTR_H_
xgboost::IntrusivePtr
Implementation of Intrusive Pointer. A smart pointer that points to an object with an embedded refere...
Definition: intrusive_ptr.h:73
xgboost::IntrusivePtr::IntrusivePtr
IntrusivePtr(IntrusivePtr &&that) noexcept
Definition: intrusive_ptr.h:112
xgboost::IntrusivePtr::Hash
Definition: intrusive_ptr.h:94
std::swap
void swap(xgboost::IntrusivePtr< T > &x, xgboost::IntrusivePtr< T > &y) noexcept
Definition: intrusive_ptr.h:209
xgboost::operator<
bool operator<(IntrusivePtr< T > const &x, IntrusivePtr< T > const &y) noexcept
Definition: intrusive_ptr.h:180
xgboost::operator>
bool operator>(IntrusivePtr< T > const &x, IntrusivePtr< T > const &y) noexcept
Definition: intrusive_ptr.h:190
xgboost::IntrusivePtrCell::IntrusivePtrCell
IntrusivePtrCell() noexcept=default
xgboost::IntrusivePtr::operator=
IntrusivePtr< T > & operator=(IntrusivePtr< T > const &that)
Definition: intrusive_ptr.h:116
xgboost::operator<<
std::basic_ostream< E, T > & operator<<(std::basic_ostream< E, T > &os, IntrusivePtr< Y > const &p)
Definition: intrusive_ptr.h:200
xgboost::IntrusivePtr::reset
void reset()
Definition: intrusive_ptr.h:125
xgboost::IntrusivePtrCell::Count
int32_t Count() const
Definition: intrusive_ptr.h:35
xgboost::IntrusivePtr::get
element_type * get() const noexcept
Definition: intrusive_ptr.h:133
xgboost::IntrusivePtrRefCount
IntrusivePtrCell & IntrusivePtrRefCount(T const *ptr) noexcept
User defined function for returning embedded reference count.
xgboost::operator<=
bool operator<=(IntrusivePtr< T > const &x, IntrusivePtr< T > const &y) noexcept
Definition: intrusive_ptr.h:185
xgboost::IntrusivePtr::swap
void swap(IntrusivePtr< T > &that) noexcept
Definition: intrusive_ptr.h:144
xgboost::IntrusivePtr::IntrusivePtr
IntrusivePtr(T *p)
Contruct an IntrusivePtr from raw pointer. IntrusivePtr takes the ownership.
Definition: intrusive_ptr.h:104
xgboost::IntrusivePtr::use_count
int32_t use_count() noexcept
Definition: intrusive_ptr.h:137
xgboost::operator!=
bool operator!=(IntrusivePtr< T > const &x, IntrusivePtr< U > const &y) noexcept
Definition: intrusive_ptr.h:155
xgboost::IntrusivePtr::operator=
IntrusivePtr< T > & operator=(IntrusivePtr< T > &&that) noexcept
Definition: intrusive_ptr.h:120
xgboost::IntrusivePtr::~IntrusivePtr
~IntrusivePtr()
Definition: intrusive_ptr.h:114
xgboost::IntrusivePtrCell
Helper class for embedding reference counting into client objects. See https://www....
Definition: intrusive_ptr.h:20
xgboost::IntrusivePtr::reset
void reset(element_type *that)
Definition: intrusive_ptr.h:129
xgboost::IntrusivePtr::operator->
element_type * operator->() const noexcept
Definition: intrusive_ptr.h:132
xgboost::IntrusivePtr::operator*
element_type & operator*() const noexcept
Definition: intrusive_ptr.h:131
xgboost::IntrusivePtr::ptr_
T * ptr_
Definition: intrusive_ptr.h:90
xgboost::operator>=
bool operator>=(IntrusivePtr< T > const &x, IntrusivePtr< T > const &y) noexcept
Definition: intrusive_ptr.h:195
std
Definition: intrusive_ptr.h:207
xgboost::IntrusivePtr::IntrusivePtr
IntrusivePtr() noexcept=default
xgboost::Value
Definition: json.h:25
xgboost::IntrusivePtr::Hash::operator()
std::size_t operator()(IntrusivePtr< element_type > const &ptr) const noexcept
Definition: intrusive_ptr.h:95
xgboost::operator==
bool operator==(IntrusivePtr< T > const &x, IntrusivePtr< U > const &y) noexcept
Definition: intrusive_ptr.h:150
xgboost
namespace of xgboost
Definition: base.h:110