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 instrinsics 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 effictive C++
73 // warnings down to a minumum
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 template<class Y> explicit SharingPtr(Y* p);
142 template<class Y> explicit SharingPtr(Y* p, imp::shared_count *ctrl_block);
143 template<class Y> SharingPtr(const SharingPtr<Y>& r, element_type *p);
144 SharingPtr(const SharingPtr& r);
146 SharingPtr(const SharingPtr<Y>& r);
150 SharingPtr& operator=(const SharingPtr& r);
151 template<class Y> SharingPtr& operator=(const SharingPtr<Y>& r);
153 void swap(SharingPtr& r);
155 template<class Y> void reset(Y* p);
157 element_type* get() const {return ptr_;}
158 element_type& operator*() const {return *ptr_;}
159 element_type* operator->() const {return ptr_;}
160 long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
161 bool unique() const {return use_count() == 1;}
162 bool empty() const {return cntrl_ == 0;}
163 operator nat*() const {return (nat*)get();}
165 static SharingPtr<T> make_shared();
168 static SharingPtr<T> make_shared(A0&);
170 template<class A0, class A1>
171 static SharingPtr<T> make_shared(A0&, A1&);
173 template<class A0, class A1, class A2>
174 static SharingPtr<T> make_shared(A0&, A1&, A2&);
176 template<class A0, class A1, class A2, class A3>
177 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
179 template<class A0, class A1, class A2, class A3, class A4>
180 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
184 template <class U> friend class SharingPtr;
189 SharingPtr<T>::SharingPtr()
197 SharingPtr<T>::SharingPtr(Y* p)
200 std::unique_ptr<Y> hold(p);
201 typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
202 cntrl_ = new _CntrlBlk(p);
208 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
209 : ptr_(p), cntrl_(cntrl_block)
216 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
221 cntrl_->add_shared();
226 SharingPtr<T>::SharingPtr(const SharingPtr& r)
231 cntrl_->add_shared();
237 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
242 cntrl_->add_shared();
246 SharingPtr<T>::~SharingPtr()
249 cntrl_->release_shared();
255 SharingPtr<T>::operator=(const SharingPtr& r)
257 SharingPtr(r).swap(*this);
265 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
267 SharingPtr(r).swap(*this);
274 SharingPtr<T>::swap(SharingPtr& r)
276 std::swap(ptr_, r.ptr_);
277 std::swap(cntrl_, r.cntrl_);
283 SharingPtr<T>::reset()
285 SharingPtr().swap(*this);
292 SharingPtr<T>::reset(Y* p)
294 SharingPtr(p).swap(*this);
299 SharingPtr<T>::make_shared()
301 typedef imp::shared_ptr_emplace<T> CntrlBlk;
303 r.cntrl_ = new CntrlBlk();
304 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
311 SharingPtr<T>::make_shared(A0& a0)
313 typedef imp::shared_ptr_emplace<T> CntrlBlk;
315 r.cntrl_ = new CntrlBlk(a0);
316 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
321 template<class A0, class A1>
323 SharingPtr<T>::make_shared(A0& a0, A1& a1)
325 typedef imp::shared_ptr_emplace<T> CntrlBlk;
327 r.cntrl_ = new CntrlBlk(a0, a1);
328 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
333 template<class A0, class A1, class A2>
335 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
337 typedef imp::shared_ptr_emplace<T> CntrlBlk;
339 r.cntrl_ = new CntrlBlk(a0, a1, a2);
340 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
345 template<class A0, class A1, class A2, class A3>
347 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
349 typedef imp::shared_ptr_emplace<T> CntrlBlk;
351 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
352 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
357 template<class A0, class A1, class A2, class A3, class A4>
359 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
361 typedef imp::shared_ptr_emplace<T> CntrlBlk;
363 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
364 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
373 return SharingPtr<T>::make_shared();
376 template<class T, class A0>
381 return SharingPtr<T>::make_shared(a0);
384 template<class T, class A0, class A1>
387 make_shared(A0& a0, A1& a1)
389 return SharingPtr<T>::make_shared(a0, a1);
392 template<class T, class A0, class A1, class A2>
395 make_shared(A0& a0, A1& a1, A2& a2)
397 return SharingPtr<T>::make_shared(a0, a1, a2);
400 template<class T, class A0, class A1, class A2, class A3>
403 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
405 return SharingPtr<T>::make_shared(a0, a1, a2, a3);
408 template<class T, class A0, class A1, class A2, class A3, class A4>
411 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
413 return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
417 template<class T, class U>
420 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
422 return __x.get() == __y.get();
425 template<class T, class U>
428 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
430 return !(__x == __y);
433 template<class T, class U>
436 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
438 return __x.get() < __y.get();
444 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
449 template<class T, class U>
452 static_pointer_cast(const SharingPtr<U>& r)
454 return SharingPtr<T>(r, static_cast<T*>(r.get()));
457 template<class T, class U>
459 const_pointer_cast(const SharingPtr<U>& r)
461 return SharingPtr<T>(r, const_cast<T*>(r.get()));
465 class LoggingSharingPtr
466 : public SharingPtr<T>
468 typedef SharingPtr<T> base;
471 typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
472 // action: false means increment just happened
473 // true means decrement is about to happen
480 LoggingSharingPtr() : cb_(0), baton_(0) {}
481 LoggingSharingPtr(Callback cb, void* baton)
482 : cb_(cb), baton_(baton)
485 cb_(baton_, *this, false);
489 LoggingSharingPtr(Y* p)
490 : base(p), cb_(0), baton_(0) {}
493 LoggingSharingPtr(Y* p, Callback cb, void* baton)
494 : base(p), cb_(cb), baton_(baton)
497 cb_(baton_, *this, false);
503 cb_(baton_, *this, true);
506 LoggingSharingPtr(const LoggingSharingPtr& p)
507 : base(p), cb_(p.cb_), baton_(p.baton_)
510 cb_(baton_, *this, false);
513 LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
516 cb_(baton_, *this, true);
521 cb_(baton_, *this, false);
528 cb_(baton_, *this, true);
536 cb_(baton_, *this, true);
539 cb_(baton_, *this, false);
542 void SetCallback(Callback cb, void* baton)
557 class IntrusiveSharingPtr;
560 class ReferenceCountedBase
563 explicit ReferenceCountedBase()
577 return shared_owners_ + 1;
583 friend class IntrusiveSharingPtr<T>;
586 ReferenceCountedBase(const ReferenceCountedBase&);
587 ReferenceCountedBase& operator=(const ReferenceCountedBase&);
592 lldb_private::ReferenceCountedBase<T>::add_shared()
595 _InterlockedIncrement(&shared_owners_);
603 lldb_private::ReferenceCountedBase<T>::release_shared()
606 if (_InterlockedDecrement(&shared_owners_) == -1)
608 if (--shared_owners_ == -1)
610 delete static_cast<T*>(this);
615 class ReferenceCountedBaseVirtual : public imp::shared_count
618 explicit ReferenceCountedBaseVirtual () :
619 imp::shared_count(-1)
624 ~ReferenceCountedBaseVirtual ()
628 virtual void on_zero_shared ();
634 ReferenceCountedBaseVirtual<T>::on_zero_shared()
638 template <typename T>
639 class IntrusiveSharingPtr
642 typedef T element_type;
645 IntrusiveSharingPtr () :
651 IntrusiveSharingPtr (T* ptr) :
657 IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) :
664 IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
671 operator= (const IntrusiveSharingPtr& rhs)
677 template <class X> IntrusiveSharingPtr&
678 operator= (const IntrusiveSharingPtr<X>& rhs)
691 ~IntrusiveSharingPtr()
694 #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
695 // NULL out the pointer in objects which can help with leaks detection.
696 // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or
697 // when none of the LLDB_CONFIGURATION_XXX macros are defined since
698 // those would be builds for release. But for debug and release builds
699 // that are for development, we NULL out the pointers to catch potential
702 #endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
723 explicit operator bool() const
729 swap (IntrusiveSharingPtr& rhs)
731 std::swap(ptr_, rhs.ptr_);
732 #if defined (ENABLE_SP_LOGGING)
733 track_sp (this, ptr_, use_count());
734 track_sp (&rhs, rhs.ptr_, rhs.use_count());
741 IntrusiveSharingPtr(ptr).swap(*this);
748 return ptr_->use_count();
755 return use_count () == 1;
767 #if defined (ENABLE_SP_LOGGING)
768 track_sp (this, ptr_, ptr_->use_count());
777 #if defined (ENABLE_SP_LOGGING)
778 track_sp (this, NULL, ptr_->use_count() - 1);
780 ptr_->release_shared();
785 template<class T, class U>
786 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
788 return lhs.get() == rhs.get();
791 template<class T, class U>
792 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
794 return lhs.get() != rhs.get();
797 template<class T, class U>
798 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
800 return lhs.get() == rhs;
803 template<class T, class U>
804 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
806 return lhs.get() != rhs;
809 template<class T, class U>
810 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
812 return lhs == rhs.get();
815 template<class T, class U>
816 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
818 return lhs != rhs.get();
821 } // namespace lldb_private
823 #endif // utility_SharingPtr_h_