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);
158 element_type* get() const {return ptr_;}
159 element_type& operator*() const {return *ptr_;}
160 element_type* operator->() const {return ptr_;}
161 long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
162 bool unique() const {return use_count() == 1;}
163 bool empty() const {return cntrl_ == 0;}
164 operator nat*() const {return (nat*)get();}
166 static SharingPtr<T> make_shared();
169 static SharingPtr<T> make_shared(A0&);
171 template<class A0, class A1>
172 static SharingPtr<T> make_shared(A0&, A1&);
174 template<class A0, class A1, class A2>
175 static SharingPtr<T> make_shared(A0&, A1&, A2&);
177 template<class A0, class A1, class A2, class A3>
178 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
180 template<class A0, class A1, class A2, class A3, class A4>
181 static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
185 template <class U> friend class SharingPtr;
190 SharingPtr<T>::SharingPtr()
198 SharingPtr<T>::SharingPtr(std::nullptr_t)
206 SharingPtr<T>::SharingPtr(Y* p)
209 std::unique_ptr<Y> hold(p);
210 typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
211 cntrl_ = new _CntrlBlk(p);
217 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
218 : ptr_(p), cntrl_(cntrl_block)
225 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
230 cntrl_->add_shared();
235 SharingPtr<T>::SharingPtr(const SharingPtr& r)
240 cntrl_->add_shared();
246 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
251 cntrl_->add_shared();
255 SharingPtr<T>::~SharingPtr()
258 cntrl_->release_shared();
264 SharingPtr<T>::operator=(const SharingPtr& r)
266 SharingPtr(r).swap(*this);
274 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
276 SharingPtr(r).swap(*this);
283 SharingPtr<T>::swap(SharingPtr& r)
285 std::swap(ptr_, r.ptr_);
286 std::swap(cntrl_, r.cntrl_);
292 SharingPtr<T>::reset()
294 SharingPtr().swap(*this);
301 SharingPtr<T>::reset(Y* p)
303 SharingPtr(p).swap(*this);
308 SharingPtr<T>::make_shared()
310 typedef imp::shared_ptr_emplace<T> CntrlBlk;
312 r.cntrl_ = new CntrlBlk();
313 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
320 SharingPtr<T>::make_shared(A0& a0)
322 typedef imp::shared_ptr_emplace<T> CntrlBlk;
324 r.cntrl_ = new CntrlBlk(a0);
325 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
330 template<class A0, class A1>
332 SharingPtr<T>::make_shared(A0& a0, A1& a1)
334 typedef imp::shared_ptr_emplace<T> CntrlBlk;
336 r.cntrl_ = new CntrlBlk(a0, a1);
337 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
342 template<class A0, class A1, class A2>
344 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
346 typedef imp::shared_ptr_emplace<T> CntrlBlk;
348 r.cntrl_ = new CntrlBlk(a0, a1, a2);
349 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
354 template<class A0, class A1, class A2, class A3>
356 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
358 typedef imp::shared_ptr_emplace<T> CntrlBlk;
360 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
361 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
366 template<class A0, class A1, class A2, class A3, class A4>
368 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
370 typedef imp::shared_ptr_emplace<T> CntrlBlk;
372 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
373 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
382 return SharingPtr<T>::make_shared();
385 template<class T, class A0>
390 return SharingPtr<T>::make_shared(a0);
393 template<class T, class A0, class A1>
396 make_shared(A0& a0, A1& a1)
398 return SharingPtr<T>::make_shared(a0, a1);
401 template<class T, class A0, class A1, class A2>
404 make_shared(A0& a0, A1& a1, A2& a2)
406 return SharingPtr<T>::make_shared(a0, a1, a2);
409 template<class T, class A0, class A1, class A2, class A3>
412 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
414 return SharingPtr<T>::make_shared(a0, a1, a2, a3);
417 template<class T, class A0, class A1, class A2, class A3, class A4>
420 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
422 return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
426 template<class T, class U>
429 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
431 return __x.get() == __y.get();
434 template<class T, class U>
437 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
439 return !(__x == __y);
442 template<class T, class U>
445 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
447 return __x.get() < __y.get();
453 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
458 template<class T, class U>
461 static_pointer_cast(const SharingPtr<U>& r)
463 return SharingPtr<T>(r, static_cast<T*>(r.get()));
466 template<class T, class U>
468 const_pointer_cast(const SharingPtr<U>& r)
470 return SharingPtr<T>(r, const_cast<T*>(r.get()));
474 class LoggingSharingPtr
475 : public SharingPtr<T>
477 typedef SharingPtr<T> base;
480 typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
481 // action: false means increment just happened
482 // true means decrement is about to happen
489 LoggingSharingPtr() : cb_(0), baton_(0) {}
490 LoggingSharingPtr(Callback cb, void* baton)
491 : cb_(cb), baton_(baton)
494 cb_(baton_, *this, false);
498 LoggingSharingPtr(Y* p)
499 : base(p), cb_(0), baton_(0) {}
502 LoggingSharingPtr(Y* p, Callback cb, void* baton)
503 : base(p), cb_(cb), baton_(baton)
506 cb_(baton_, *this, false);
512 cb_(baton_, *this, true);
515 LoggingSharingPtr(const LoggingSharingPtr& p)
516 : base(p), cb_(p.cb_), baton_(p.baton_)
519 cb_(baton_, *this, false);
522 LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
525 cb_(baton_, *this, true);
530 cb_(baton_, *this, false);
537 cb_(baton_, *this, true);
545 cb_(baton_, *this, true);
548 cb_(baton_, *this, false);
551 void SetCallback(Callback cb, void* baton)
566 class IntrusiveSharingPtr;
569 class ReferenceCountedBase
572 explicit ReferenceCountedBase()
586 return shared_owners_ + 1;
592 friend class IntrusiveSharingPtr<T>;
595 ReferenceCountedBase(const ReferenceCountedBase&);
596 ReferenceCountedBase& operator=(const ReferenceCountedBase&);
601 lldb_private::ReferenceCountedBase<T>::add_shared()
604 _InterlockedIncrement(&shared_owners_);
612 lldb_private::ReferenceCountedBase<T>::release_shared()
615 if (_InterlockedDecrement(&shared_owners_) == -1)
617 if (--shared_owners_ == -1)
619 delete static_cast<T*>(this);
624 class ReferenceCountedBaseVirtual : public imp::shared_count
627 explicit ReferenceCountedBaseVirtual () :
628 imp::shared_count(-1)
633 ~ReferenceCountedBaseVirtual ()
637 virtual void on_zero_shared ();
643 ReferenceCountedBaseVirtual<T>::on_zero_shared()
647 template <typename T>
648 class IntrusiveSharingPtr
651 typedef T element_type;
654 IntrusiveSharingPtr () :
660 IntrusiveSharingPtr (T* ptr) :
666 IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) :
673 IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
680 operator= (const IntrusiveSharingPtr& rhs)
686 template <class X> IntrusiveSharingPtr&
687 operator= (const IntrusiveSharingPtr<X>& rhs)
700 ~IntrusiveSharingPtr()
703 #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
704 // NULL out the pointer in objects which can help with leaks detection.
705 // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or
706 // when none of the LLDB_CONFIGURATION_XXX macros are defined since
707 // those would be builds for release. But for debug and release builds
708 // that are for development, we NULL out the pointers to catch potential
711 #endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
732 explicit operator bool() const
738 swap (IntrusiveSharingPtr& rhs)
740 std::swap(ptr_, rhs.ptr_);
741 #if defined (ENABLE_SP_LOGGING)
742 track_sp (this, ptr_, use_count());
743 track_sp (&rhs, rhs.ptr_, rhs.use_count());
750 IntrusiveSharingPtr(ptr).swap(*this);
757 return ptr_->use_count();
764 return use_count () == 1;
776 #if defined (ENABLE_SP_LOGGING)
777 track_sp (this, ptr_, ptr_->use_count());
786 #if defined (ENABLE_SP_LOGGING)
787 track_sp (this, NULL, ptr_->use_count() - 1);
789 ptr_->release_shared();
794 template<class T, class U>
795 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
797 return lhs.get() == rhs.get();
800 template<class T, class U>
801 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
803 return lhs.get() != rhs.get();
806 template<class T, class U>
807 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
809 return lhs.get() == rhs;
812 template<class T, class U>
813 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
815 return lhs.get() != rhs;
818 template<class T, class U>
819 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
821 return lhs == rhs.get();
824 template<class T, class U>
825 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
827 return lhs != rhs.get();
830 } // namespace lldb_private
832 #endif // utility_SharingPtr_h_