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