1 //===---------------------SharingPtr.h --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef utility_SharingPtr_h_
11 #define utility_SharingPtr_h_
16 // Microsoft Visual C++ currently does not enable std::atomic to work
17 // in CLR mode - as such we need to "hack around it" for MSVC++ builds only
18 // using Windows specific intrinsics instead of the C++11 atomic support
25 //#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
26 #if defined (ENABLE_SP_LOGGING)
28 extern "C" void track_sp (void *sp_this, void *ptr, long count);
32 namespace lldb_private {
38 shared_count(const shared_count&);
39 shared_count& operator=(const shared_count&);
45 std::atomic<long> shared_owners_;
47 virtual ~shared_count();
49 virtual void on_zero_shared() = 0;
52 explicit shared_count(long refs = 0)
53 : shared_owners_(refs) {}
56 void release_shared();
57 long use_count() const {return shared_owners_ + 1;}
61 class shared_ptr_pointer
66 shared_ptr_pointer(T p)
70 virtual void on_zero_shared();
72 // Outlaw copy constructor and assignment operator to keep effective C++
73 // warnings down to a minimum
74 shared_ptr_pointer (const shared_ptr_pointer &);
75 shared_ptr_pointer & operator=(const shared_ptr_pointer &);
80 shared_ptr_pointer<T>::on_zero_shared()
86 class shared_ptr_emplace
96 shared_ptr_emplace(A0& a0)
99 template <class A0, class A1>
100 shared_ptr_emplace(A0& a0, A1& a1)
103 template <class A0, class A1, class A2>
104 shared_ptr_emplace(A0& a0, A1& a1, A2& a2)
105 : data_(a0, a1, a2) {}
107 template <class A0, class A1, class A2, class A3>
108 shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3)
109 : data_(a0, a1, a2, a3) {}
111 template <class A0, class A1, class A2, class A3, class A4>
112 shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
113 : data_(a0, a1, a2, a3, a4) {}
116 virtual void on_zero_shared();
118 T* get() {return &data_;}
123 shared_ptr_emplace<T>::on_zero_shared()
133 typedef T element_type;
136 imp::shared_count* cntrl_;
138 struct nat {int for_bool_;};
141 SharingPtr(std::nullptr_t);
142 template<class Y> explicit SharingPtr(Y* p);
143 template<class Y> explicit SharingPtr(Y* p, imp::shared_count *ctrl_block);
144 template<class Y> SharingPtr(const SharingPtr<Y>& r, element_type *p);
145 SharingPtr(const SharingPtr& r);
147 SharingPtr(const SharingPtr<Y>& r);
151 SharingPtr& operator=(const SharingPtr& r);
152 template<class Y> SharingPtr& operator=(const SharingPtr<Y>& r);
154 void swap(SharingPtr& r);
156 template<class Y> void reset(Y* p);
157 void reset(std::nullptr_t);
159 element_type* get() const {return ptr_;}
160 element_type& operator*() const {return *ptr_;}
161 element_type* operator->() const {return ptr_;}
162 long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
163 bool unique() const {return use_count() == 1;}
164 bool empty() const {return cntrl_ == 0;}
165 operator nat*() const {return (nat*)get();}
167 static SharingPtr<T> make_shared();
170 static SharingPtr<T> make_shared(A0&);
172 template<class A0, class A1>
173 static SharingPtr<T> make_shared(A0&, A1&);
175 template<class A0, class A1, class A2>
176 static SharingPtr<T> make_shared(A0&, A1&, A2&);
178 template<class A0, class A1, class A2, class A3>
179 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
181 template<class A0, class A1, class A2, class A3, class A4>
182 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
186 template <class U> friend class SharingPtr;
191 SharingPtr<T>::SharingPtr()
199 SharingPtr<T>::SharingPtr(std::nullptr_t)
207 SharingPtr<T>::SharingPtr(Y* p)
210 std::unique_ptr<Y> hold(p);
211 typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
212 cntrl_ = new _CntrlBlk(p);
218 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
219 : ptr_(p), cntrl_(cntrl_block)
226 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
231 cntrl_->add_shared();
236 SharingPtr<T>::SharingPtr(const SharingPtr& r)
241 cntrl_->add_shared();
247 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
252 cntrl_->add_shared();
256 SharingPtr<T>::~SharingPtr()
259 cntrl_->release_shared();
265 SharingPtr<T>::operator=(const SharingPtr& r)
267 SharingPtr(r).swap(*this);
275 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
277 SharingPtr(r).swap(*this);
284 SharingPtr<T>::swap(SharingPtr& r)
286 std::swap(ptr_, r.ptr_);
287 std::swap(cntrl_, r.cntrl_);
293 SharingPtr<T>::reset()
295 SharingPtr().swap(*this);
301 SharingPtr<T>::reset (std::nullptr_t p)
310 SharingPtr<T>::reset(Y* p)
312 SharingPtr(p).swap(*this);
317 SharingPtr<T>::make_shared()
319 typedef imp::shared_ptr_emplace<T> CntrlBlk;
321 r.cntrl_ = new CntrlBlk();
322 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
329 SharingPtr<T>::make_shared(A0& a0)
331 typedef imp::shared_ptr_emplace<T> CntrlBlk;
333 r.cntrl_ = new CntrlBlk(a0);
334 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
339 template<class A0, class A1>
341 SharingPtr<T>::make_shared(A0& a0, A1& a1)
343 typedef imp::shared_ptr_emplace<T> CntrlBlk;
345 r.cntrl_ = new CntrlBlk(a0, a1);
346 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
351 template<class A0, class A1, class A2>
353 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
355 typedef imp::shared_ptr_emplace<T> CntrlBlk;
357 r.cntrl_ = new CntrlBlk(a0, a1, a2);
358 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
363 template<class A0, class A1, class A2, class A3>
365 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
367 typedef imp::shared_ptr_emplace<T> CntrlBlk;
369 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
370 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
375 template<class A0, class A1, class A2, class A3, class A4>
377 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
379 typedef imp::shared_ptr_emplace<T> CntrlBlk;
381 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
382 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
391 return SharingPtr<T>::make_shared();
394 template<class T, class A0>
399 return SharingPtr<T>::make_shared(a0);
402 template<class T, class A0, class A1>
405 make_shared(A0& a0, A1& a1)
407 return SharingPtr<T>::make_shared(a0, a1);
410 template<class T, class A0, class A1, class A2>
413 make_shared(A0& a0, A1& a1, A2& a2)
415 return SharingPtr<T>::make_shared(a0, a1, a2);
418 template<class T, class A0, class A1, class A2, class A3>
421 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
423 return SharingPtr<T>::make_shared(a0, a1, a2, a3);
426 template<class T, class A0, class A1, class A2, class A3, class A4>
429 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
431 return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
435 template<class T, class U>
438 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
440 return __x.get() == __y.get();
443 template<class T, class U>
446 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
448 return !(__x == __y);
451 template<class T, class U>
454 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
456 return __x.get() < __y.get();
462 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
467 template<class T, class U>
470 static_pointer_cast(const SharingPtr<U>& r)
472 return SharingPtr<T>(r, static_cast<T*>(r.get()));
475 template<class T, class U>
477 const_pointer_cast(const SharingPtr<U>& r)
479 return SharingPtr<T>(r, const_cast<T*>(r.get()));
483 class LoggingSharingPtr
484 : public SharingPtr<T>
486 typedef SharingPtr<T> base;
489 typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
490 // action: false means increment just happened
491 // true means decrement is about to happen
498 LoggingSharingPtr() : cb_(0), baton_(0) {}
499 LoggingSharingPtr(Callback cb, void* baton)
500 : cb_(cb), baton_(baton)
503 cb_(baton_, *this, false);
507 LoggingSharingPtr(Y* p)
508 : base(p), cb_(0), baton_(0) {}
511 LoggingSharingPtr(Y* p, Callback cb, void* baton)
512 : base(p), cb_(cb), baton_(baton)
515 cb_(baton_, *this, false);
521 cb_(baton_, *this, true);
524 LoggingSharingPtr(const LoggingSharingPtr& p)
525 : base(p), cb_(p.cb_), baton_(p.baton_)
528 cb_(baton_, *this, false);
531 LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
534 cb_(baton_, *this, true);
539 cb_(baton_, *this, false);
546 cb_(baton_, *this, true);
554 cb_(baton_, *this, true);
557 cb_(baton_, *this, false);
560 void SetCallback(Callback cb, void* baton)
575 class IntrusiveSharingPtr;
578 class ReferenceCountedBase
581 explicit ReferenceCountedBase()
595 return shared_owners_ + 1;
601 friend class IntrusiveSharingPtr<T>;
604 ReferenceCountedBase(const ReferenceCountedBase&);
605 ReferenceCountedBase& operator=(const ReferenceCountedBase&);
610 lldb_private::ReferenceCountedBase<T>::add_shared()
613 _InterlockedIncrement(&shared_owners_);
621 lldb_private::ReferenceCountedBase<T>::release_shared()
624 if (_InterlockedDecrement(&shared_owners_) == -1)
626 if (--shared_owners_ == -1)
628 delete static_cast<T*>(this);
633 class ReferenceCountedBaseVirtual : public imp::shared_count
636 explicit ReferenceCountedBaseVirtual () :
637 imp::shared_count(-1)
642 ~ReferenceCountedBaseVirtual ()
646 virtual void on_zero_shared ();
652 ReferenceCountedBaseVirtual<T>::on_zero_shared()
656 template <typename T>
657 class IntrusiveSharingPtr
660 typedef T element_type;
663 IntrusiveSharingPtr () :
669 IntrusiveSharingPtr (T* ptr) :
675 IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) :
682 IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
689 operator= (const IntrusiveSharingPtr& rhs)
695 template <class X> IntrusiveSharingPtr&
696 operator= (const IntrusiveSharingPtr<X>& rhs)
709 ~IntrusiveSharingPtr()
712 #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
713 // NULL out the pointer in objects which can help with leaks detection.
714 // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or
715 // when none of the LLDB_CONFIGURATION_XXX macros are defined since
716 // those would be builds for release. But for debug and release builds
717 // that are for development, we NULL out the pointers to catch potential
720 #endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
741 explicit operator bool() const
747 swap (IntrusiveSharingPtr& rhs)
749 std::swap(ptr_, rhs.ptr_);
750 #if defined (ENABLE_SP_LOGGING)
751 track_sp (this, ptr_, use_count());
752 track_sp (&rhs, rhs.ptr_, rhs.use_count());
759 IntrusiveSharingPtr(ptr).swap(*this);
766 return ptr_->use_count();
773 return use_count () == 1;
785 #if defined (ENABLE_SP_LOGGING)
786 track_sp (this, ptr_, ptr_->use_count());
795 #if defined (ENABLE_SP_LOGGING)
796 track_sp (this, NULL, ptr_->use_count() - 1);
798 ptr_->release_shared();
803 template<class T, class U>
804 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
806 return lhs.get() == rhs.get();
809 template<class T, class U>
810 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
812 return lhs.get() != rhs.get();
815 template<class T, class U>
816 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
818 return lhs.get() == rhs;
821 template<class T, class U>
822 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
824 return lhs.get() != rhs;
827 template<class T, class U>
828 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
830 return lhs == rhs.get();
833 template<class T, class U>
834 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
836 return lhs != rhs.get();
839 } // namespace lldb_private
841 #endif // utility_SharingPtr_h_