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