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