1254721Semaste//===---------------------SharingPtr.h --------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#ifndef utility_SharingPtr_h_
10254721Semaste#define utility_SharingPtr_h_
11254721Semaste
12254721Semaste#include <memory>
13254721Semaste
14341825Sdim// Microsoft Visual C++ currently does not enable std::atomic to work in CLR
15341825Sdim// mode - as such we need to "hack around it" for MSVC++ builds only using
16341825Sdim// Windows specific intrinsics instead of the C++11 atomic support
17258054Semaste#ifdef _MSC_VER
18258054Semaste#include <intrin.h>
19258054Semaste#else
20258054Semaste#include <atomic>
21258054Semaste#endif
22258054Semaste
23321369Sdim#include <stddef.h>
24321369Sdim
25296417Sdim
26254721Semaste//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
27314564Sdim#if defined(ENABLE_SP_LOGGING)
28254721Semaste
29314564Sdimextern "C" void track_sp(void *sp_this, void *ptr, long count);
30254721Semaste
31254721Semaste#endif
32254721Semaste
33254721Semastenamespace lldb_private {
34254721Semaste
35254721Semastenamespace imp {
36254721Semaste
37314564Sdimclass shared_count {
38353358Sdim  shared_count(const shared_count &) = delete;
39353358Sdim  shared_count &operator=(const shared_count &) = delete;
40314564Sdim
41296417Sdimpublic:
42314564Sdim  explicit shared_count(long refs = 0) : shared_owners_(refs) {}
43296417Sdim
44314564Sdim  void add_shared();
45314564Sdim  void release_shared();
46314564Sdim  long use_count() const { return shared_owners_ + 1; }
47314564Sdim
48254721Semasteprotected:
49258054Semaste#ifdef _MSC_VER
50314564Sdim  long shared_owners_;
51258054Semaste#else
52314564Sdim  std::atomic<long> shared_owners_;
53258054Semaste#endif
54314564Sdim  virtual ~shared_count();
55296417Sdim
56254721Semasteprivate:
57314564Sdim  virtual void on_zero_shared() = 0;
58254721Semaste};
59254721Semaste
60314564Sdimtemplate <class T> class shared_ptr_pointer : public shared_count {
61314564Sdim  T data_;
62314564Sdim
63254721Semastepublic:
64314564Sdim  shared_ptr_pointer(T p) : data_(p) {}
65254721Semaste
66254721Semasteprivate:
67314564Sdim  void on_zero_shared() override;
68254721Semaste
69353358Sdim  shared_ptr_pointer(const shared_ptr_pointer &) = delete;
70353358Sdim  shared_ptr_pointer &operator=(const shared_ptr_pointer &) = delete;
71254721Semaste};
72254721Semaste
73314564Sdimtemplate <class T> void shared_ptr_pointer<T>::on_zero_shared() {
74314564Sdim  delete data_;
75254721Semaste}
76254721Semaste
77314564Sdimtemplate <class T> class shared_ptr_emplace : public shared_count {
78314564Sdim  T data_;
79314564Sdim
80254721Semastepublic:
81314564Sdim  shared_ptr_emplace() : data_() {}
82254721Semaste
83314564Sdim  template <class A0> shared_ptr_emplace(A0 &a0) : data_(a0) {}
84254721Semaste
85314564Sdim  template <class A0, class A1>
86314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1) : data_(a0, a1) {}
87254721Semaste
88314564Sdim  template <class A0, class A1, class A2>
89314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2) : data_(a0, a1, a2) {}
90254721Semaste
91314564Sdim  template <class A0, class A1, class A2, class A3>
92314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3) : data_(a0, a1, a2, a3) {}
93254721Semaste
94314564Sdim  template <class A0, class A1, class A2, class A3, class A4>
95314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4)
96314564Sdim      : data_(a0, a1, a2, a3, a4) {}
97254721Semaste
98254721Semasteprivate:
99314564Sdim  void on_zero_shared() override;
100296417Sdim
101254721Semastepublic:
102314564Sdim  T *get() { return &data_; }
103254721Semaste};
104254721Semaste
105314564Sdimtemplate <class T> void shared_ptr_emplace<T>::on_zero_shared() {}
106254721Semaste
107296417Sdim} // namespace imp
108254721Semaste
109314564Sdimtemplate <class T> class SharingPtr {
110314564Sdimpublic:
111314564Sdim  typedef T element_type;
112296417Sdim
113254721Semasteprivate:
114314564Sdim  element_type *ptr_;
115314564Sdim  imp::shared_count *cntrl_;
116254721Semaste
117314564Sdim  struct nat {
118314564Sdim    int for_bool_;
119314564Sdim  };
120296417Sdim
121254721Semastepublic:
122314564Sdim  SharingPtr();
123314564Sdim  SharingPtr(std::nullptr_t);
124314564Sdim  template <class Y> explicit SharingPtr(Y *p);
125314564Sdim  template <class Y> explicit SharingPtr(Y *p, imp::shared_count *ctrl_block);
126314564Sdim  template <class Y> SharingPtr(const SharingPtr<Y> &r, element_type *p);
127314564Sdim  SharingPtr(const SharingPtr &r);
128314564Sdim  template <class Y> SharingPtr(const SharingPtr<Y> &r);
129254721Semaste
130314564Sdim  ~SharingPtr();
131254721Semaste
132314564Sdim  SharingPtr &operator=(const SharingPtr &r);
133314564Sdim  template <class Y> SharingPtr &operator=(const SharingPtr<Y> &r);
134254721Semaste
135314564Sdim  void swap(SharingPtr &r);
136314564Sdim  void reset();
137314564Sdim  template <class Y> void reset(Y *p);
138314564Sdim  void reset(std::nullptr_t);
139254721Semaste
140314564Sdim  element_type *get() const { return ptr_; }
141314564Sdim  element_type &operator*() const { return *ptr_; }
142314564Sdim  element_type *operator->() const { return ptr_; }
143314564Sdim  long use_count() const { return cntrl_ ? cntrl_->use_count() : 0; }
144314564Sdim  bool unique() const { return use_count() == 1; }
145314564Sdim  bool empty() const { return cntrl_ == nullptr; }
146314564Sdim  operator nat *() const { return (nat *)get(); }
147254721Semaste
148314564Sdim  static SharingPtr<T> make_shared();
149254721Semaste
150314564Sdim  template <class A0> static SharingPtr<T> make_shared(A0 &);
151254721Semaste
152314564Sdim  template <class A0, class A1> static SharingPtr<T> make_shared(A0 &, A1 &);
153254721Semaste
154314564Sdim  template <class A0, class A1, class A2>
155314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &);
156254721Semaste
157314564Sdim  template <class A0, class A1, class A2, class A3>
158314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &);
159254721Semaste
160314564Sdim  template <class A0, class A1, class A2, class A3, class A4>
161314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &, A4 &);
162254721Semaste
163254721Semasteprivate:
164314564Sdim  template <class U> friend class SharingPtr;
165254721Semaste};
166254721Semaste
167314564Sdimtemplate <class T>
168314564Sdiminline SharingPtr<T>::SharingPtr() : ptr_(nullptr), cntrl_(nullptr) {}
169254721Semaste
170314564Sdimtemplate <class T>
171314564Sdiminline SharingPtr<T>::SharingPtr(std::nullptr_t)
172314564Sdim    : ptr_(nullptr), cntrl_(nullptr) {}
173314564Sdim
174314564Sdimtemplate <class T>
175314564Sdimtemplate <class Y>
176314564SdimSharingPtr<T>::SharingPtr(Y *p) : ptr_(p), cntrl_(nullptr) {
177314564Sdim  std::unique_ptr<Y> hold(p);
178314564Sdim  typedef imp::shared_ptr_pointer<Y *> _CntrlBlk;
179314564Sdim  cntrl_ = new _CntrlBlk(p);
180314564Sdim  hold.release();
181254721Semaste}
182254721Semaste
183314564Sdimtemplate <class T>
184314564Sdimtemplate <class Y>
185314564SdimSharingPtr<T>::SharingPtr(Y *p, imp::shared_count *cntrl_block)
186314564Sdim    : ptr_(p), cntrl_(cntrl_block) {}
187314564Sdim
188314564Sdimtemplate <class T>
189314564Sdimtemplate <class Y>
190314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r, element_type *p)
191314564Sdim    : ptr_(p), cntrl_(r.cntrl_) {
192314564Sdim  if (cntrl_)
193314564Sdim    cntrl_->add_shared();
194254721Semaste}
195254721Semaste
196314564Sdimtemplate <class T>
197314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr &r)
198314564Sdim    : ptr_(r.ptr_), cntrl_(r.cntrl_) {
199314564Sdim  if (cntrl_)
200314564Sdim    cntrl_->add_shared();
201254721Semaste}
202254721Semaste
203314564Sdimtemplate <class T>
204314564Sdimtemplate <class Y>
205314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r)
206314564Sdim    : ptr_(r.ptr_), cntrl_(r.cntrl_) {
207314564Sdim  if (cntrl_)
208314564Sdim    cntrl_->add_shared();
209254721Semaste}
210254721Semaste
211314564Sdimtemplate <class T> SharingPtr<T>::~SharingPtr() {
212314564Sdim  if (cntrl_)
213314564Sdim    cntrl_->release_shared();
214254721Semaste}
215254721Semaste
216314564Sdimtemplate <class T>
217314564Sdiminline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr &r) {
218314564Sdim  SharingPtr(r).swap(*this);
219314564Sdim  return *this;
220254721Semaste}
221254721Semaste
222314564Sdimtemplate <class T>
223314564Sdimtemplate <class Y>
224314564Sdiminline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr<Y> &r) {
225314564Sdim  SharingPtr(r).swap(*this);
226314564Sdim  return *this;
227254721Semaste}
228254721Semaste
229314564Sdimtemplate <class T> inline void SharingPtr<T>::swap(SharingPtr &r) {
230314564Sdim  std::swap(ptr_, r.ptr_);
231314564Sdim  std::swap(cntrl_, r.cntrl_);
232254721Semaste}
233254721Semaste
234314564Sdimtemplate <class T> inline void SharingPtr<T>::reset() {
235314564Sdim  SharingPtr().swap(*this);
236254721Semaste}
237254721Semaste
238314564Sdimtemplate <class T> inline void SharingPtr<T>::reset(std::nullptr_t p) {
239314564Sdim  reset();
240254721Semaste}
241254721Semaste
242314564Sdimtemplate <class T> template <class Y> inline void SharingPtr<T>::reset(Y *p) {
243314564Sdim  SharingPtr(p).swap(*this);
244288943Sdim}
245254721Semaste
246314564Sdimtemplate <class T> SharingPtr<T> SharingPtr<T>::make_shared() {
247314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
248314564Sdim  SharingPtr<T> r;
249314564Sdim  r.cntrl_ = new CntrlBlk();
250314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
251314564Sdim  return r;
252254721Semaste}
253254721Semaste
254314564Sdimtemplate <class T>
255314564Sdimtemplate <class A0>
256314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0) {
257314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
258314564Sdim  SharingPtr<T> r;
259314564Sdim  r.cntrl_ = new CntrlBlk(a0);
260314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
261314564Sdim  return r;
262254721Semaste}
263254721Semaste
264314564Sdimtemplate <class T>
265314564Sdimtemplate <class A0, class A1>
266314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1) {
267314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
268314564Sdim  SharingPtr<T> r;
269314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1);
270314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
271314564Sdim  return r;
272254721Semaste}
273254721Semaste
274314564Sdimtemplate <class T>
275314564Sdimtemplate <class A0, class A1, class A2>
276314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2) {
277314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
278314564Sdim  SharingPtr<T> r;
279314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2);
280314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
281314564Sdim  return r;
282254721Semaste}
283254721Semaste
284314564Sdimtemplate <class T>
285314564Sdimtemplate <class A0, class A1, class A2, class A3>
286314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) {
287314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
288314564Sdim  SharingPtr<T> r;
289314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
290314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
291314564Sdim  return r;
292254721Semaste}
293254721Semaste
294314564Sdimtemplate <class T>
295314564Sdimtemplate <class A0, class A1, class A2, class A3, class A4>
296314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3,
297314564Sdim                                         A4 &a4) {
298314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
299314564Sdim  SharingPtr<T> r;
300314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
301314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
302314564Sdim  return r;
303254721Semaste}
304254721Semaste
305314564Sdimtemplate <class T> inline SharingPtr<T> make_shared() {
306314564Sdim  return SharingPtr<T>::make_shared();
307254721Semaste}
308254721Semaste
309314564Sdimtemplate <class T, class A0> inline SharingPtr<T> make_shared(A0 &a0) {
310314564Sdim  return SharingPtr<T>::make_shared(a0);
311254721Semaste}
312254721Semaste
313314564Sdimtemplate <class T, class A0, class A1>
314314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1) {
315314564Sdim  return SharingPtr<T>::make_shared(a0, a1);
316254721Semaste}
317254721Semaste
318314564Sdimtemplate <class T, class A0, class A1, class A2>
319314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2) {
320314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2);
321254721Semaste}
322254721Semaste
323314564Sdimtemplate <class T, class A0, class A1, class A2, class A3>
324314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) {
325314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2, a3);
326254721Semaste}
327254721Semaste
328314564Sdimtemplate <class T, class A0, class A1, class A2, class A3, class A4>
329314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) {
330314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
331254721Semaste}
332254721Semaste
333314564Sdimtemplate <class T, class U>
334314564Sdiminline bool operator==(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
335314564Sdim  return __x.get() == __y.get();
336254721Semaste}
337254721Semaste
338314564Sdimtemplate <class T, class U>
339314564Sdiminline bool operator!=(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
340314564Sdim  return !(__x == __y);
341254721Semaste}
342254721Semaste
343314564Sdimtemplate <class T, class U>
344314564Sdiminline bool operator<(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
345314564Sdim  return __x.get() < __y.get();
346254721Semaste}
347254721Semaste
348314564Sdimtemplate <class T> inline void swap(SharingPtr<T> &__x, SharingPtr<T> &__y) {
349314564Sdim  __x.swap(__y);
350254721Semaste}
351254721Semaste
352314564Sdimtemplate <class T, class U>
353314564Sdiminline SharingPtr<T> static_pointer_cast(const SharingPtr<U> &r) {
354314564Sdim  return SharingPtr<T>(r, static_cast<T *>(r.get()));
355254721Semaste}
356254721Semaste
357314564Sdimtemplate <class T, class U>
358314564SdimSharingPtr<T> const_pointer_cast(const SharingPtr<U> &r) {
359314564Sdim  return SharingPtr<T>(r, const_cast<T *>(r.get()));
360254721Semaste}
361254721Semaste
362314564Sdimtemplate <class T> class LoggingSharingPtr : public SharingPtr<T> {
363314564Sdim  typedef SharingPtr<T> base;
364254721Semaste
365254721Semastepublic:
366314564Sdim  typedef void (*Callback)(void *, const LoggingSharingPtr &, bool action);
367314564Sdim  // action:  false means increment just happened
368314564Sdim  //          true  means decrement is about to happen
369254721Semaste
370314564Sdim  LoggingSharingPtr() : cb_(0), baton_(nullptr) {}
371254721Semaste
372314564Sdim  LoggingSharingPtr(Callback cb, void *baton) : cb_(cb), baton_(baton) {
373314564Sdim    if (cb_)
374314564Sdim      cb_(baton_, *this, false);
375314564Sdim  }
376254721Semaste
377314564Sdim  template <class Y>
378314564Sdim  LoggingSharingPtr(Y *p) : base(p), cb_(0), baton_(nullptr) {}
379254721Semaste
380314564Sdim  template <class Y>
381314564Sdim  LoggingSharingPtr(Y *p, Callback cb, void *baton)
382314564Sdim      : base(p), cb_(cb), baton_(baton) {
383314564Sdim    if (cb_)
384314564Sdim      cb_(baton_, *this, false);
385314564Sdim  }
386254721Semaste
387314564Sdim  ~LoggingSharingPtr() {
388314564Sdim    if (cb_)
389314564Sdim      cb_(baton_, *this, true);
390314564Sdim  }
391254721Semaste
392314564Sdim  LoggingSharingPtr(const LoggingSharingPtr &p)
393314564Sdim      : base(p), cb_(p.cb_), baton_(p.baton_) {
394314564Sdim    if (cb_)
395314564Sdim      cb_(baton_, *this, false);
396314564Sdim  }
397254721Semaste
398314564Sdim  LoggingSharingPtr &operator=(const LoggingSharingPtr &p) {
399314564Sdim    if (cb_)
400314564Sdim      cb_(baton_, *this, true);
401314564Sdim    base::operator=(p);
402314564Sdim    cb_ = p.cb_;
403314564Sdim    baton_ = p.baton_;
404314564Sdim    if (cb_)
405314564Sdim      cb_(baton_, *this, false);
406314564Sdim    return *this;
407314564Sdim  }
408254721Semaste
409314564Sdim  void reset() {
410314564Sdim    if (cb_)
411314564Sdim      cb_(baton_, *this, true);
412314564Sdim    base::reset();
413314564Sdim  }
414254721Semaste
415314564Sdim  template <class Y> void reset(Y *p) {
416314564Sdim    if (cb_)
417314564Sdim      cb_(baton_, *this, true);
418314564Sdim    base::reset(p);
419314564Sdim    if (cb_)
420314564Sdim      cb_(baton_, *this, false);
421314564Sdim  }
422254721Semaste
423314564Sdim  void SetCallback(Callback cb, void *baton) {
424314564Sdim    cb_ = cb;
425314564Sdim    baton_ = baton;
426314564Sdim  }
427296417Sdim
428314564Sdim  void ClearCallback() {
429314564Sdim    cb_ = 0;
430314564Sdim    baton_ = 0;
431314564Sdim  }
432314564Sdim
433296417Sdimprivate:
434314564Sdim  Callback cb_;
435314564Sdim  void *baton_;
436254721Semaste};
437296417Sdim
438314564Sdimtemplate <class T> class IntrusiveSharingPtr;
439254721Semaste
440314564Sdimtemplate <class T> class ReferenceCountedBase {
441254721Semastepublic:
442314564Sdim  explicit ReferenceCountedBase() : shared_owners_(-1) {}
443254721Semaste
444314564Sdim  void add_shared();
445254721Semaste
446314564Sdim  void release_shared();
447314564Sdim
448314564Sdim  long use_count() const { return shared_owners_ + 1; }
449314564Sdim
450254721Semasteprotected:
451314564Sdim  long shared_owners_;
452314564Sdim
453314564Sdim  friend class IntrusiveSharingPtr<T>;
454314564Sdim
455254721Semasteprivate:
456353358Sdim  ReferenceCountedBase(const ReferenceCountedBase &) = delete;
457353358Sdim  ReferenceCountedBase &operator=(const ReferenceCountedBase &) = delete;
458254721Semaste};
459254721Semaste
460314564Sdimtemplate <class T> void lldb_private::ReferenceCountedBase<T>::add_shared() {
461258054Semaste#ifdef _MSC_VER
462314564Sdim  _InterlockedIncrement(&shared_owners_);
463258054Semaste#else
464314564Sdim  ++shared_owners_;
465258054Semaste#endif
466314564Sdim}
467314564Sdim
468314564Sdimtemplate <class T>
469314564Sdimvoid lldb_private::ReferenceCountedBase<T>::release_shared() {
470258054Semaste#ifdef _MSC_VER
471314564Sdim  if (_InterlockedDecrement(&shared_owners_) == -1)
472258054Semaste#else
473314564Sdim  if (--shared_owners_ == -1)
474258054Semaste#endif
475314564Sdim    delete static_cast<T *>(this);
476314564Sdim}
477254721Semaste
478254721Semastetemplate <class T>
479314564Sdimclass ReferenceCountedBaseVirtual : public imp::shared_count {
480254721Semastepublic:
481314564Sdim  explicit ReferenceCountedBaseVirtual() : imp::shared_count(-1) {}
482296417Sdim
483314564Sdim  ~ReferenceCountedBaseVirtual() override = default;
484296417Sdim
485314564Sdim  void on_zero_shared() override;
486254721Semaste};
487254721Semaste
488314564Sdimtemplate <class T> void ReferenceCountedBaseVirtual<T>::on_zero_shared() {}
489254721Semaste
490314564Sdimtemplate <typename T> class IntrusiveSharingPtr {
491254721Semastepublic:
492314564Sdim  typedef T element_type;
493314564Sdim
494314564Sdim  explicit IntrusiveSharingPtr() : ptr_(0) {}
495314564Sdim
496314564Sdim  explicit IntrusiveSharingPtr(T *ptr) : ptr_(ptr) { add_shared(); }
497314564Sdim
498314564Sdim  IntrusiveSharingPtr(const IntrusiveSharingPtr &rhs) : ptr_(rhs.ptr_) {
499314564Sdim    add_shared();
500314564Sdim  }
501314564Sdim
502314564Sdim  template <class X>
503314564Sdim  IntrusiveSharingPtr(const IntrusiveSharingPtr<X> &rhs) : ptr_(rhs.get()) {
504314564Sdim    add_shared();
505314564Sdim  }
506314564Sdim
507314564Sdim  IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr &rhs) {
508314564Sdim    reset(rhs.get());
509314564Sdim    return *this;
510314564Sdim  }
511314564Sdim
512314564Sdim  template <class X>
513314564Sdim  IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr<X> &rhs) {
514314564Sdim    reset(rhs.get());
515314564Sdim    return *this;
516314564Sdim  }
517314564Sdim
518314564Sdim  IntrusiveSharingPtr &operator=(T *ptr) {
519314564Sdim    reset(ptr);
520314564Sdim    return *this;
521314564Sdim  }
522314564Sdim
523314564Sdim  ~IntrusiveSharingPtr() {
524314564Sdim    release_shared();
525314564Sdim    ptr_ = nullptr;
526314564Sdim  }
527314564Sdim
528314564Sdim  T &operator*() const { return *ptr_; }
529314564Sdim
530314564Sdim  T *operator->() const { return ptr_; }
531314564Sdim
532314564Sdim  T *get() const { return ptr_; }
533314564Sdim
534314564Sdim  explicit operator bool() const { return ptr_ != 0; }
535314564Sdim
536314564Sdim  void swap(IntrusiveSharingPtr &rhs) {
537314564Sdim    std::swap(ptr_, rhs.ptr_);
538314564Sdim#if defined(ENABLE_SP_LOGGING)
539314564Sdim    track_sp(this, ptr_, use_count());
540314564Sdim    track_sp(&rhs, rhs.ptr_, rhs.use_count());
541254721Semaste#endif
542314564Sdim  }
543254721Semaste
544314564Sdim  void reset(T *ptr = nullptr) { IntrusiveSharingPtr(ptr).swap(*this); }
545254721Semaste
546314564Sdim  long use_count() const {
547314564Sdim    if (ptr_)
548314564Sdim      return ptr_->use_count();
549314564Sdim    return 0;
550314564Sdim  }
551254721Semaste
552314564Sdim  bool unique() const { return use_count() == 1; }
553314564Sdim
554254721Semasteprivate:
555314564Sdim  element_type *ptr_;
556314564Sdim
557314564Sdim  void add_shared() {
558314564Sdim    if (ptr_) {
559314564Sdim      ptr_->add_shared();
560314564Sdim#if defined(ENABLE_SP_LOGGING)
561314564Sdim      track_sp(this, ptr_, ptr_->use_count());
562254721Semaste#endif
563254721Semaste    }
564314564Sdim  }
565314564Sdim  void release_shared() {
566314564Sdim    if (ptr_) {
567314564Sdim#if defined(ENABLE_SP_LOGGING)
568314564Sdim      track_sp(this, nullptr, ptr_->use_count() - 1);
569254721Semaste#endif
570314564Sdim      ptr_->release_shared();
571254721Semaste    }
572314564Sdim  }
573254721Semaste};
574254721Semaste
575314564Sdimtemplate <class T, class U>
576314564Sdiminline bool operator==(const IntrusiveSharingPtr<T> &lhs,
577314564Sdim                       const IntrusiveSharingPtr<U> &rhs) {
578314564Sdim  return lhs.get() == rhs.get();
579254721Semaste}
580254721Semaste
581314564Sdimtemplate <class T, class U>
582314564Sdiminline bool operator!=(const IntrusiveSharingPtr<T> &lhs,
583314564Sdim                       const IntrusiveSharingPtr<U> &rhs) {
584314564Sdim  return lhs.get() != rhs.get();
585254721Semaste}
586254721Semaste
587314564Sdimtemplate <class T, class U>
588314564Sdiminline bool operator==(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
589314564Sdim  return lhs.get() == rhs;
590254721Semaste}
591254721Semaste
592314564Sdimtemplate <class T, class U>
593314564Sdiminline bool operator!=(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
594314564Sdim  return lhs.get() != rhs;
595254721Semaste}
596254721Semaste
597314564Sdimtemplate <class T, class U>
598314564Sdiminline bool operator==(T *lhs, const IntrusiveSharingPtr<U> &rhs) {
599314564Sdim  return lhs == rhs.get();
600254721Semaste}
601254721Semaste
602314564Sdimtemplate <class T, class U>
603314564Sdiminline bool operator!=(T *lhs, const IntrusiveSharingPtr<U> &rhs) {
604314564Sdim  return lhs != rhs.get();
605254721Semaste}
606254721Semaste
607254721Semaste} // namespace lldb_private
608254721Semaste
609296417Sdim#endif // utility_SharingPtr_h_
610