SharingPtr.h revision 341825
1254721Semaste//===---------------------SharingPtr.h --------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#ifndef utility_SharingPtr_h_
11254721Semaste#define utility_SharingPtr_h_
12254721Semaste
13296417Sdim// C Includes
14296417Sdim// C++ Includes
15254721Semaste#include <memory>
16254721Semaste
17341825Sdim// Microsoft Visual C++ currently does not enable std::atomic to work in CLR
18341825Sdim// mode - as such we need to "hack around it" for MSVC++ builds only using
19341825Sdim// Windows specific intrinsics instead of the C++11 atomic support
20258054Semaste#ifdef _MSC_VER
21258054Semaste#include <intrin.h>
22258054Semaste#else
23258054Semaste#include <atomic>
24258054Semaste#endif
25258054Semaste
26321369Sdim#include <stddef.h>
27321369Sdim
28296417Sdim// Other libraries and framework includes
29296417Sdim// Project includes
30296417Sdim
31254721Semaste//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
32314564Sdim#if defined(ENABLE_SP_LOGGING)
33254721Semaste
34314564Sdimextern "C" void track_sp(void *sp_this, void *ptr, long count);
35254721Semaste
36254721Semaste#endif
37254721Semaste
38254721Semastenamespace lldb_private {
39254721Semaste
40254721Semastenamespace imp {
41254721Semaste
42314564Sdimclass shared_count {
43314564Sdim  shared_count(const shared_count &);
44314564Sdim  shared_count &operator=(const shared_count &);
45314564Sdim
46296417Sdimpublic:
47314564Sdim  explicit shared_count(long refs = 0) : shared_owners_(refs) {}
48296417Sdim
49314564Sdim  void add_shared();
50314564Sdim  void release_shared();
51314564Sdim  long use_count() const { return shared_owners_ + 1; }
52314564Sdim
53254721Semasteprotected:
54258054Semaste#ifdef _MSC_VER
55314564Sdim  long shared_owners_;
56258054Semaste#else
57314564Sdim  std::atomic<long> shared_owners_;
58258054Semaste#endif
59314564Sdim  virtual ~shared_count();
60296417Sdim
61254721Semasteprivate:
62314564Sdim  virtual void on_zero_shared() = 0;
63254721Semaste};
64254721Semaste
65314564Sdimtemplate <class T> class shared_ptr_pointer : public shared_count {
66314564Sdim  T data_;
67314564Sdim
68254721Semastepublic:
69314564Sdim  shared_ptr_pointer(T p) : data_(p) {}
70254721Semaste
71254721Semasteprivate:
72314564Sdim  void on_zero_shared() override;
73254721Semaste
74314564Sdim  // Outlaw copy constructor and assignment operator to keep effective C++
75314564Sdim  // warnings down to a minimum
76314564Sdim  shared_ptr_pointer(const shared_ptr_pointer &);
77314564Sdim  shared_ptr_pointer &operator=(const shared_ptr_pointer &);
78254721Semaste};
79254721Semaste
80314564Sdimtemplate <class T> void shared_ptr_pointer<T>::on_zero_shared() {
81314564Sdim  delete data_;
82254721Semaste}
83254721Semaste
84314564Sdimtemplate <class T> class shared_ptr_emplace : public shared_count {
85314564Sdim  T data_;
86314564Sdim
87254721Semastepublic:
88314564Sdim  shared_ptr_emplace() : data_() {}
89254721Semaste
90314564Sdim  template <class A0> shared_ptr_emplace(A0 &a0) : data_(a0) {}
91254721Semaste
92314564Sdim  template <class A0, class A1>
93314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1) : data_(a0, a1) {}
94254721Semaste
95314564Sdim  template <class A0, class A1, class A2>
96314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2) : data_(a0, a1, a2) {}
97254721Semaste
98314564Sdim  template <class A0, class A1, class A2, class A3>
99314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3) : data_(a0, a1, a2, a3) {}
100254721Semaste
101314564Sdim  template <class A0, class A1, class A2, class A3, class A4>
102314564Sdim  shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4)
103314564Sdim      : data_(a0, a1, a2, a3, a4) {}
104254721Semaste
105254721Semasteprivate:
106314564Sdim  void on_zero_shared() override;
107296417Sdim
108254721Semastepublic:
109314564Sdim  T *get() { return &data_; }
110254721Semaste};
111254721Semaste
112314564Sdimtemplate <class T> void shared_ptr_emplace<T>::on_zero_shared() {}
113254721Semaste
114296417Sdim} // namespace imp
115254721Semaste
116314564Sdimtemplate <class T> class SharingPtr {
117314564Sdimpublic:
118314564Sdim  typedef T element_type;
119296417Sdim
120254721Semasteprivate:
121314564Sdim  element_type *ptr_;
122314564Sdim  imp::shared_count *cntrl_;
123254721Semaste
124314564Sdim  struct nat {
125314564Sdim    int for_bool_;
126314564Sdim  };
127296417Sdim
128254721Semastepublic:
129314564Sdim  SharingPtr();
130314564Sdim  SharingPtr(std::nullptr_t);
131314564Sdim  template <class Y> explicit SharingPtr(Y *p);
132314564Sdim  template <class Y> explicit SharingPtr(Y *p, imp::shared_count *ctrl_block);
133314564Sdim  template <class Y> SharingPtr(const SharingPtr<Y> &r, element_type *p);
134314564Sdim  SharingPtr(const SharingPtr &r);
135314564Sdim  template <class Y> SharingPtr(const SharingPtr<Y> &r);
136254721Semaste
137314564Sdim  ~SharingPtr();
138254721Semaste
139314564Sdim  SharingPtr &operator=(const SharingPtr &r);
140314564Sdim  template <class Y> SharingPtr &operator=(const SharingPtr<Y> &r);
141254721Semaste
142314564Sdim  void swap(SharingPtr &r);
143314564Sdim  void reset();
144314564Sdim  template <class Y> void reset(Y *p);
145314564Sdim  void reset(std::nullptr_t);
146254721Semaste
147314564Sdim  element_type *get() const { return ptr_; }
148314564Sdim  element_type &operator*() const { return *ptr_; }
149314564Sdim  element_type *operator->() const { return ptr_; }
150314564Sdim  long use_count() const { return cntrl_ ? cntrl_->use_count() : 0; }
151314564Sdim  bool unique() const { return use_count() == 1; }
152314564Sdim  bool empty() const { return cntrl_ == nullptr; }
153314564Sdim  operator nat *() const { return (nat *)get(); }
154254721Semaste
155314564Sdim  static SharingPtr<T> make_shared();
156254721Semaste
157314564Sdim  template <class A0> static SharingPtr<T> make_shared(A0 &);
158254721Semaste
159314564Sdim  template <class A0, class A1> static SharingPtr<T> make_shared(A0 &, A1 &);
160254721Semaste
161314564Sdim  template <class A0, class A1, class A2>
162314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &);
163254721Semaste
164314564Sdim  template <class A0, class A1, class A2, class A3>
165314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &);
166254721Semaste
167314564Sdim  template <class A0, class A1, class A2, class A3, class A4>
168314564Sdim  static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &, A4 &);
169254721Semaste
170254721Semasteprivate:
171314564Sdim  template <class U> friend class SharingPtr;
172254721Semaste};
173254721Semaste
174314564Sdimtemplate <class T>
175314564Sdiminline SharingPtr<T>::SharingPtr() : ptr_(nullptr), cntrl_(nullptr) {}
176254721Semaste
177314564Sdimtemplate <class T>
178314564Sdiminline SharingPtr<T>::SharingPtr(std::nullptr_t)
179314564Sdim    : ptr_(nullptr), cntrl_(nullptr) {}
180314564Sdim
181314564Sdimtemplate <class T>
182314564Sdimtemplate <class Y>
183314564SdimSharingPtr<T>::SharingPtr(Y *p) : ptr_(p), cntrl_(nullptr) {
184314564Sdim  std::unique_ptr<Y> hold(p);
185314564Sdim  typedef imp::shared_ptr_pointer<Y *> _CntrlBlk;
186314564Sdim  cntrl_ = new _CntrlBlk(p);
187314564Sdim  hold.release();
188254721Semaste}
189254721Semaste
190314564Sdimtemplate <class T>
191314564Sdimtemplate <class Y>
192314564SdimSharingPtr<T>::SharingPtr(Y *p, imp::shared_count *cntrl_block)
193314564Sdim    : ptr_(p), cntrl_(cntrl_block) {}
194314564Sdim
195314564Sdimtemplate <class T>
196314564Sdimtemplate <class Y>
197314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r, element_type *p)
198314564Sdim    : ptr_(p), cntrl_(r.cntrl_) {
199314564Sdim  if (cntrl_)
200314564Sdim    cntrl_->add_shared();
201254721Semaste}
202254721Semaste
203314564Sdimtemplate <class T>
204314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr &r)
205314564Sdim    : ptr_(r.ptr_), cntrl_(r.cntrl_) {
206314564Sdim  if (cntrl_)
207314564Sdim    cntrl_->add_shared();
208254721Semaste}
209254721Semaste
210314564Sdimtemplate <class T>
211314564Sdimtemplate <class Y>
212314564Sdiminline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r)
213314564Sdim    : ptr_(r.ptr_), cntrl_(r.cntrl_) {
214314564Sdim  if (cntrl_)
215314564Sdim    cntrl_->add_shared();
216254721Semaste}
217254721Semaste
218314564Sdimtemplate <class T> SharingPtr<T>::~SharingPtr() {
219314564Sdim  if (cntrl_)
220314564Sdim    cntrl_->release_shared();
221254721Semaste}
222254721Semaste
223314564Sdimtemplate <class T>
224314564Sdiminline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr &r) {
225314564Sdim  SharingPtr(r).swap(*this);
226314564Sdim  return *this;
227254721Semaste}
228254721Semaste
229314564Sdimtemplate <class T>
230314564Sdimtemplate <class Y>
231314564Sdiminline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr<Y> &r) {
232314564Sdim  SharingPtr(r).swap(*this);
233314564Sdim  return *this;
234254721Semaste}
235254721Semaste
236314564Sdimtemplate <class T> inline void SharingPtr<T>::swap(SharingPtr &r) {
237314564Sdim  std::swap(ptr_, r.ptr_);
238314564Sdim  std::swap(cntrl_, r.cntrl_);
239254721Semaste}
240254721Semaste
241314564Sdimtemplate <class T> inline void SharingPtr<T>::reset() {
242314564Sdim  SharingPtr().swap(*this);
243254721Semaste}
244254721Semaste
245314564Sdimtemplate <class T> inline void SharingPtr<T>::reset(std::nullptr_t p) {
246314564Sdim  reset();
247254721Semaste}
248254721Semaste
249314564Sdimtemplate <class T> template <class Y> inline void SharingPtr<T>::reset(Y *p) {
250314564Sdim  SharingPtr(p).swap(*this);
251288943Sdim}
252254721Semaste
253314564Sdimtemplate <class T> SharingPtr<T> SharingPtr<T>::make_shared() {
254314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
255314564Sdim  SharingPtr<T> r;
256314564Sdim  r.cntrl_ = new CntrlBlk();
257314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
258314564Sdim  return r;
259254721Semaste}
260254721Semaste
261314564Sdimtemplate <class T>
262314564Sdimtemplate <class A0>
263314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0) {
264314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
265314564Sdim  SharingPtr<T> r;
266314564Sdim  r.cntrl_ = new CntrlBlk(a0);
267314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
268314564Sdim  return r;
269254721Semaste}
270254721Semaste
271314564Sdimtemplate <class T>
272314564Sdimtemplate <class A0, class A1>
273314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1) {
274314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
275314564Sdim  SharingPtr<T> r;
276314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1);
277314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
278314564Sdim  return r;
279254721Semaste}
280254721Semaste
281314564Sdimtemplate <class T>
282314564Sdimtemplate <class A0, class A1, class A2>
283314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2) {
284314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
285314564Sdim  SharingPtr<T> r;
286314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2);
287314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
288314564Sdim  return r;
289254721Semaste}
290254721Semaste
291314564Sdimtemplate <class T>
292314564Sdimtemplate <class A0, class A1, class A2, class A3>
293314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) {
294314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
295314564Sdim  SharingPtr<T> r;
296314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
297314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
298314564Sdim  return r;
299254721Semaste}
300254721Semaste
301314564Sdimtemplate <class T>
302314564Sdimtemplate <class A0, class A1, class A2, class A3, class A4>
303314564SdimSharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3,
304314564Sdim                                         A4 &a4) {
305314564Sdim  typedef imp::shared_ptr_emplace<T> CntrlBlk;
306314564Sdim  SharingPtr<T> r;
307314564Sdim  r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
308314564Sdim  r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get();
309314564Sdim  return r;
310254721Semaste}
311254721Semaste
312314564Sdimtemplate <class T> inline SharingPtr<T> make_shared() {
313314564Sdim  return SharingPtr<T>::make_shared();
314254721Semaste}
315254721Semaste
316314564Sdimtemplate <class T, class A0> inline SharingPtr<T> make_shared(A0 &a0) {
317314564Sdim  return SharingPtr<T>::make_shared(a0);
318254721Semaste}
319254721Semaste
320314564Sdimtemplate <class T, class A0, class A1>
321314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1) {
322314564Sdim  return SharingPtr<T>::make_shared(a0, a1);
323254721Semaste}
324254721Semaste
325314564Sdimtemplate <class T, class A0, class A1, class A2>
326314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2) {
327314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2);
328254721Semaste}
329254721Semaste
330314564Sdimtemplate <class T, class A0, class A1, class A2, class A3>
331314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) {
332314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2, a3);
333254721Semaste}
334254721Semaste
335314564Sdimtemplate <class T, class A0, class A1, class A2, class A3, class A4>
336314564Sdiminline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) {
337314564Sdim  return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
338254721Semaste}
339254721Semaste
340314564Sdimtemplate <class T, class U>
341314564Sdiminline bool operator==(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
342314564Sdim  return __x.get() == __y.get();
343254721Semaste}
344254721Semaste
345314564Sdimtemplate <class T, class U>
346314564Sdiminline bool operator!=(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
347314564Sdim  return !(__x == __y);
348254721Semaste}
349254721Semaste
350314564Sdimtemplate <class T, class U>
351314564Sdiminline bool operator<(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
352314564Sdim  return __x.get() < __y.get();
353254721Semaste}
354254721Semaste
355314564Sdimtemplate <class T> inline void swap(SharingPtr<T> &__x, SharingPtr<T> &__y) {
356314564Sdim  __x.swap(__y);
357254721Semaste}
358254721Semaste
359314564Sdimtemplate <class T, class U>
360314564Sdiminline SharingPtr<T> static_pointer_cast(const SharingPtr<U> &r) {
361314564Sdim  return SharingPtr<T>(r, static_cast<T *>(r.get()));
362254721Semaste}
363254721Semaste
364314564Sdimtemplate <class T, class U>
365314564SdimSharingPtr<T> const_pointer_cast(const SharingPtr<U> &r) {
366314564Sdim  return SharingPtr<T>(r, const_cast<T *>(r.get()));
367254721Semaste}
368254721Semaste
369314564Sdimtemplate <class T> class LoggingSharingPtr : public SharingPtr<T> {
370314564Sdim  typedef SharingPtr<T> base;
371254721Semaste
372254721Semastepublic:
373314564Sdim  typedef void (*Callback)(void *, const LoggingSharingPtr &, bool action);
374314564Sdim  // action:  false means increment just happened
375314564Sdim  //          true  means decrement is about to happen
376254721Semaste
377314564Sdim  LoggingSharingPtr() : cb_(0), baton_(nullptr) {}
378254721Semaste
379314564Sdim  LoggingSharingPtr(Callback cb, void *baton) : cb_(cb), baton_(baton) {
380314564Sdim    if (cb_)
381314564Sdim      cb_(baton_, *this, false);
382314564Sdim  }
383254721Semaste
384314564Sdim  template <class Y>
385314564Sdim  LoggingSharingPtr(Y *p) : base(p), cb_(0), baton_(nullptr) {}
386254721Semaste
387314564Sdim  template <class Y>
388314564Sdim  LoggingSharingPtr(Y *p, Callback cb, void *baton)
389314564Sdim      : base(p), cb_(cb), baton_(baton) {
390314564Sdim    if (cb_)
391314564Sdim      cb_(baton_, *this, false);
392314564Sdim  }
393254721Semaste
394314564Sdim  ~LoggingSharingPtr() {
395314564Sdim    if (cb_)
396314564Sdim      cb_(baton_, *this, true);
397314564Sdim  }
398254721Semaste
399314564Sdim  LoggingSharingPtr(const LoggingSharingPtr &p)
400314564Sdim      : base(p), cb_(p.cb_), baton_(p.baton_) {
401314564Sdim    if (cb_)
402314564Sdim      cb_(baton_, *this, false);
403314564Sdim  }
404254721Semaste
405314564Sdim  LoggingSharingPtr &operator=(const LoggingSharingPtr &p) {
406314564Sdim    if (cb_)
407314564Sdim      cb_(baton_, *this, true);
408314564Sdim    base::operator=(p);
409314564Sdim    cb_ = p.cb_;
410314564Sdim    baton_ = p.baton_;
411314564Sdim    if (cb_)
412314564Sdim      cb_(baton_, *this, false);
413314564Sdim    return *this;
414314564Sdim  }
415254721Semaste
416314564Sdim  void reset() {
417314564Sdim    if (cb_)
418314564Sdim      cb_(baton_, *this, true);
419314564Sdim    base::reset();
420314564Sdim  }
421254721Semaste
422314564Sdim  template <class Y> void reset(Y *p) {
423314564Sdim    if (cb_)
424314564Sdim      cb_(baton_, *this, true);
425314564Sdim    base::reset(p);
426314564Sdim    if (cb_)
427314564Sdim      cb_(baton_, *this, false);
428314564Sdim  }
429254721Semaste
430314564Sdim  void SetCallback(Callback cb, void *baton) {
431314564Sdim    cb_ = cb;
432314564Sdim    baton_ = baton;
433314564Sdim  }
434296417Sdim
435314564Sdim  void ClearCallback() {
436314564Sdim    cb_ = 0;
437314564Sdim    baton_ = 0;
438314564Sdim  }
439314564Sdim
440296417Sdimprivate:
441314564Sdim  Callback cb_;
442314564Sdim  void *baton_;
443254721Semaste};
444296417Sdim
445314564Sdimtemplate <class T> class IntrusiveSharingPtr;
446254721Semaste
447314564Sdimtemplate <class T> class ReferenceCountedBase {
448254721Semastepublic:
449314564Sdim  explicit ReferenceCountedBase() : shared_owners_(-1) {}
450254721Semaste
451314564Sdim  void add_shared();
452254721Semaste
453314564Sdim  void release_shared();
454314564Sdim
455314564Sdim  long use_count() const { return shared_owners_ + 1; }
456314564Sdim
457254721Semasteprotected:
458314564Sdim  long shared_owners_;
459314564Sdim
460314564Sdim  friend class IntrusiveSharingPtr<T>;
461314564Sdim
462254721Semasteprivate:
463314564Sdim  ReferenceCountedBase(const ReferenceCountedBase &);
464314564Sdim  ReferenceCountedBase &operator=(const ReferenceCountedBase &);
465254721Semaste};
466254721Semaste
467314564Sdimtemplate <class T> void lldb_private::ReferenceCountedBase<T>::add_shared() {
468258054Semaste#ifdef _MSC_VER
469314564Sdim  _InterlockedIncrement(&shared_owners_);
470258054Semaste#else
471314564Sdim  ++shared_owners_;
472258054Semaste#endif
473314564Sdim}
474314564Sdim
475314564Sdimtemplate <class T>
476314564Sdimvoid lldb_private::ReferenceCountedBase<T>::release_shared() {
477258054Semaste#ifdef _MSC_VER
478314564Sdim  if (_InterlockedDecrement(&shared_owners_) == -1)
479258054Semaste#else
480314564Sdim  if (--shared_owners_ == -1)
481258054Semaste#endif
482314564Sdim    delete static_cast<T *>(this);
483314564Sdim}
484254721Semaste
485254721Semastetemplate <class T>
486314564Sdimclass ReferenceCountedBaseVirtual : public imp::shared_count {
487254721Semastepublic:
488314564Sdim  explicit ReferenceCountedBaseVirtual() : imp::shared_count(-1) {}
489296417Sdim
490314564Sdim  ~ReferenceCountedBaseVirtual() override = default;
491296417Sdim
492314564Sdim  void on_zero_shared() override;
493254721Semaste};
494254721Semaste
495314564Sdimtemplate <class T> void ReferenceCountedBaseVirtual<T>::on_zero_shared() {}
496254721Semaste
497314564Sdimtemplate <typename T> class IntrusiveSharingPtr {
498254721Semastepublic:
499314564Sdim  typedef T element_type;
500314564Sdim
501314564Sdim  explicit IntrusiveSharingPtr() : ptr_(0) {}
502314564Sdim
503314564Sdim  explicit IntrusiveSharingPtr(T *ptr) : ptr_(ptr) { add_shared(); }
504314564Sdim
505314564Sdim  IntrusiveSharingPtr(const IntrusiveSharingPtr &rhs) : ptr_(rhs.ptr_) {
506314564Sdim    add_shared();
507314564Sdim  }
508314564Sdim
509314564Sdim  template <class X>
510314564Sdim  IntrusiveSharingPtr(const IntrusiveSharingPtr<X> &rhs) : ptr_(rhs.get()) {
511314564Sdim    add_shared();
512314564Sdim  }
513314564Sdim
514314564Sdim  IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr &rhs) {
515314564Sdim    reset(rhs.get());
516314564Sdim    return *this;
517314564Sdim  }
518314564Sdim
519314564Sdim  template <class X>
520314564Sdim  IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr<X> &rhs) {
521314564Sdim    reset(rhs.get());
522314564Sdim    return *this;
523314564Sdim  }
524314564Sdim
525314564Sdim  IntrusiveSharingPtr &operator=(T *ptr) {
526314564Sdim    reset(ptr);
527314564Sdim    return *this;
528314564Sdim  }
529314564Sdim
530314564Sdim  ~IntrusiveSharingPtr() {
531314564Sdim    release_shared();
532314564Sdim    ptr_ = nullptr;
533314564Sdim  }
534314564Sdim
535314564Sdim  T &operator*() const { return *ptr_; }
536314564Sdim
537314564Sdim  T *operator->() const { return ptr_; }
538314564Sdim
539314564Sdim  T *get() const { return ptr_; }
540314564Sdim
541314564Sdim  explicit operator bool() const { return ptr_ != 0; }
542314564Sdim
543314564Sdim  void swap(IntrusiveSharingPtr &rhs) {
544314564Sdim    std::swap(ptr_, rhs.ptr_);
545314564Sdim#if defined(ENABLE_SP_LOGGING)
546314564Sdim    track_sp(this, ptr_, use_count());
547314564Sdim    track_sp(&rhs, rhs.ptr_, rhs.use_count());
548254721Semaste#endif
549314564Sdim  }
550254721Semaste
551314564Sdim  void reset(T *ptr = nullptr) { IntrusiveSharingPtr(ptr).swap(*this); }
552254721Semaste
553314564Sdim  long use_count() const {
554314564Sdim    if (ptr_)
555314564Sdim      return ptr_->use_count();
556314564Sdim    return 0;
557314564Sdim  }
558254721Semaste
559314564Sdim  bool unique() const { return use_count() == 1; }
560314564Sdim
561254721Semasteprivate:
562314564Sdim  element_type *ptr_;
563314564Sdim
564314564Sdim  void add_shared() {
565314564Sdim    if (ptr_) {
566314564Sdim      ptr_->add_shared();
567314564Sdim#if defined(ENABLE_SP_LOGGING)
568314564Sdim      track_sp(this, ptr_, ptr_->use_count());
569254721Semaste#endif
570254721Semaste    }
571314564Sdim  }
572314564Sdim  void release_shared() {
573314564Sdim    if (ptr_) {
574314564Sdim#if defined(ENABLE_SP_LOGGING)
575314564Sdim      track_sp(this, nullptr, ptr_->use_count() - 1);
576254721Semaste#endif
577314564Sdim      ptr_->release_shared();
578254721Semaste    }
579314564Sdim  }
580254721Semaste};
581254721Semaste
582314564Sdimtemplate <class T, class U>
583314564Sdiminline bool operator==(const IntrusiveSharingPtr<T> &lhs,
584314564Sdim                       const IntrusiveSharingPtr<U> &rhs) {
585314564Sdim  return lhs.get() == rhs.get();
586254721Semaste}
587254721Semaste
588314564Sdimtemplate <class T, class U>
589314564Sdiminline bool operator!=(const IntrusiveSharingPtr<T> &lhs,
590314564Sdim                       const IntrusiveSharingPtr<U> &rhs) {
591314564Sdim  return lhs.get() != rhs.get();
592254721Semaste}
593254721Semaste
594314564Sdimtemplate <class T, class U>
595314564Sdiminline bool operator==(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
596314564Sdim  return lhs.get() == rhs;
597254721Semaste}
598254721Semaste
599314564Sdimtemplate <class T, class U>
600314564Sdiminline bool operator!=(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
601314564Sdim  return lhs.get() != rhs;
602254721Semaste}
603254721Semaste
604314564Sdimtemplate <class T, class U>
605314564Sdiminline bool operator==(T *lhs, const IntrusiveSharingPtr<U> &rhs) {
606314564Sdim  return lhs == rhs.get();
607254721Semaste}
608254721Semaste
609314564Sdimtemplate <class T, class U>
610314564Sdiminline bool operator!=(T *lhs, const IntrusiveSharingPtr<U> &rhs) {
611314564Sdim  return lhs != rhs.get();
612254721Semaste}
613254721Semaste
614254721Semaste} // namespace lldb_private
615254721Semaste
616296417Sdim#endif // utility_SharingPtr_h_
617