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 //#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
17 #if defined (ENABLE_SP_LOGGING)
19 extern "C" void track_sp (void *sp_this, void *ptr, long count);
23 namespace lldb_private {
31 return __sync_add_and_fetch(&t, 1);
38 return __sync_add_and_fetch(&t, -1);
43 shared_count(const shared_count&);
44 shared_count& operator=(const shared_count&);
48 virtual ~shared_count();
50 virtual void on_zero_shared() = 0;
53 explicit shared_count(long refs = 0)
54 : shared_owners_(refs) {}
57 void release_shared();
58 long use_count() const {return shared_owners_ + 1;}
62 class shared_ptr_pointer
67 shared_ptr_pointer(T p)
71 virtual void on_zero_shared();
73 // Outlaw copy constructor and assignment operator to keep effictive C++
74 // warnings down to a minumum
75 shared_ptr_pointer (const shared_ptr_pointer &);
76 shared_ptr_pointer & operator=(const shared_ptr_pointer &);
81 shared_ptr_pointer<T>::on_zero_shared()
87 class shared_ptr_emplace
97 shared_ptr_emplace(A0& a0)
100 template <class A0, class A1>
101 shared_ptr_emplace(A0& a0, A1& a1)
104 template <class A0, class A1, class A2>
105 shared_ptr_emplace(A0& a0, A1& a1, A2& a2)
106 : data_(a0, a1, a2) {}
108 template <class A0, class A1, class A2, class A3>
109 shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3)
110 : data_(a0, a1, a2, a3) {}
112 template <class A0, class A1, class A2, class A3, class A4>
113 shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
114 : data_(a0, a1, a2, a3, a4) {}
117 virtual void on_zero_shared();
119 T* get() {return &data_;}
124 shared_ptr_emplace<T>::on_zero_shared()
134 typedef T element_type;
137 imp::shared_count* cntrl_;
139 struct nat {int for_bool_;};
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(Y* p)
201 std::unique_ptr<Y> hold(p);
202 typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
203 cntrl_ = new _CntrlBlk(p);
209 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
210 : ptr_(p), cntrl_(cntrl_block)
217 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
222 cntrl_->add_shared();
227 SharingPtr<T>::SharingPtr(const SharingPtr& r)
232 cntrl_->add_shared();
238 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
243 cntrl_->add_shared();
247 SharingPtr<T>::~SharingPtr()
250 cntrl_->release_shared();
256 SharingPtr<T>::operator=(const SharingPtr& r)
258 SharingPtr(r).swap(*this);
266 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
268 SharingPtr(r).swap(*this);
275 SharingPtr<T>::swap(SharingPtr& r)
277 std::swap(ptr_, r.ptr_);
278 std::swap(cntrl_, r.cntrl_);
284 SharingPtr<T>::reset()
286 SharingPtr().swap(*this);
293 SharingPtr<T>::reset(Y* p)
295 SharingPtr(p).swap(*this);
300 SharingPtr<T>::make_shared()
302 typedef imp::shared_ptr_emplace<T> CntrlBlk;
304 r.cntrl_ = new CntrlBlk();
305 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
312 SharingPtr<T>::make_shared(A0& a0)
314 typedef imp::shared_ptr_emplace<T> CntrlBlk;
316 r.cntrl_ = new CntrlBlk(a0);
317 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
322 template<class A0, class A1>
324 SharingPtr<T>::make_shared(A0& a0, A1& a1)
326 typedef imp::shared_ptr_emplace<T> CntrlBlk;
328 r.cntrl_ = new CntrlBlk(a0, a1);
329 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
334 template<class A0, class A1, class A2>
336 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
338 typedef imp::shared_ptr_emplace<T> CntrlBlk;
340 r.cntrl_ = new CntrlBlk(a0, a1, a2);
341 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
346 template<class A0, class A1, class A2, class A3>
348 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
350 typedef imp::shared_ptr_emplace<T> CntrlBlk;
352 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
353 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
358 template<class A0, class A1, class A2, class A3, class A4>
360 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
362 typedef imp::shared_ptr_emplace<T> CntrlBlk;
364 r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
365 r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
374 return SharingPtr<T>::make_shared();
377 template<class T, class A0>
382 return SharingPtr<T>::make_shared(a0);
385 template<class T, class A0, class A1>
388 make_shared(A0& a0, A1& a1)
390 return SharingPtr<T>::make_shared(a0, a1);
393 template<class T, class A0, class A1, class A2>
396 make_shared(A0& a0, A1& a1, A2& a2)
398 return SharingPtr<T>::make_shared(a0, a1, a2);
401 template<class T, class A0, class A1, class A2, class A3>
404 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
406 return SharingPtr<T>::make_shared(a0, a1, a2, a3);
409 template<class T, class A0, class A1, class A2, class A3, class A4>
412 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
414 return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
418 template<class T, class U>
421 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
423 return __x.get() == __y.get();
426 template<class T, class U>
429 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
431 return !(__x == __y);
434 template<class T, class U>
437 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
439 return __x.get() < __y.get();
445 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
450 template<class T, class U>
453 static_pointer_cast(const SharingPtr<U>& r)
455 return SharingPtr<T>(r, static_cast<T*>(r.get()));
458 template<class T, class U>
460 const_pointer_cast(const SharingPtr<U>& r)
462 return SharingPtr<T>(r, const_cast<T*>(r.get()));
466 class LoggingSharingPtr
467 : public SharingPtr<T>
469 typedef SharingPtr<T> base;
472 typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
473 // action: false means increment just happened
474 // true means decrement is about to happen
481 LoggingSharingPtr() : cb_(0), baton_(0) {}
482 LoggingSharingPtr(Callback cb, void* baton)
483 : cb_(cb), baton_(baton)
486 cb_(baton_, *this, false);
490 LoggingSharingPtr(Y* p)
491 : base(p), cb_(0), baton_(0) {}
494 LoggingSharingPtr(Y* p, Callback cb, void* baton)
495 : base(p), cb_(cb), baton_(baton)
498 cb_(baton_, *this, false);
504 cb_(baton_, *this, true);
507 LoggingSharingPtr(const LoggingSharingPtr& p)
508 : base(p), cb_(p.cb_), baton_(p.baton_)
511 cb_(baton_, *this, false);
514 LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
517 cb_(baton_, *this, true);
522 cb_(baton_, *this, false);
529 cb_(baton_, *this, true);
537 cb_(baton_, *this, true);
540 cb_(baton_, *this, false);
543 void SetCallback(Callback cb, void* baton)
558 class IntrusiveSharingPtr;
561 class ReferenceCountedBase
564 explicit ReferenceCountedBase()
578 return shared_owners_ + 1;
584 friend class IntrusiveSharingPtr<T>;
587 ReferenceCountedBase(const ReferenceCountedBase&);
588 ReferenceCountedBase& operator=(const ReferenceCountedBase&);
593 lldb_private::ReferenceCountedBase<T>::add_shared()
595 imp::increment(shared_owners_);
600 lldb_private::ReferenceCountedBase<T>::release_shared()
602 if (imp::decrement(shared_owners_) == -1)
603 delete static_cast<T*>(this);
608 class ReferenceCountedBaseVirtual : public imp::shared_count
611 explicit ReferenceCountedBaseVirtual () :
612 imp::shared_count(-1)
617 ~ReferenceCountedBaseVirtual ()
621 virtual void on_zero_shared ();
627 ReferenceCountedBaseVirtual<T>::on_zero_shared()
631 template <typename T>
632 class IntrusiveSharingPtr
635 typedef T element_type;
638 IntrusiveSharingPtr () :
644 IntrusiveSharingPtr (T* ptr) :
650 IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) :
657 IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
664 operator= (const IntrusiveSharingPtr& rhs)
670 template <class X> IntrusiveSharingPtr&
671 operator= (const IntrusiveSharingPtr<X>& rhs)
684 ~IntrusiveSharingPtr()
687 #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
688 // NULL out the pointer in objects which can help with leaks detection.
689 // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or
690 // when none of the LLDB_CONFIGURATION_XXX macros are defined since
691 // those would be builds for release. But for debug and release builds
692 // that are for development, we NULL out the pointers to catch potential
695 #endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
716 operator bool() const
722 swap (IntrusiveSharingPtr& rhs)
724 std::swap(ptr_, rhs.ptr_);
725 #if defined (ENABLE_SP_LOGGING)
726 track_sp (this, ptr_, use_count());
727 track_sp (&rhs, rhs.ptr_, rhs.use_count());
734 IntrusiveSharingPtr(ptr).swap(*this);
741 return ptr_->use_count();
748 return use_count () == 1;
760 #if defined (ENABLE_SP_LOGGING)
761 track_sp (this, ptr_, ptr_->use_count());
770 #if defined (ENABLE_SP_LOGGING)
771 track_sp (this, NULL, ptr_->use_count() - 1);
773 ptr_->release_shared();
778 template<class T, class U>
779 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
781 return lhs.get() == rhs.get();
784 template<class T, class U>
785 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
787 return lhs.get() != rhs.get();
790 template<class T, class U>
791 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
793 return lhs.get() == rhs;
796 template<class T, class U>
797 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
799 return lhs.get() != rhs;
802 template<class T, class U>
803 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
805 return lhs == rhs.get();
808 template<class T, class U>
809 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
811 return lhs != rhs.get();
814 } // namespace lldb_private
816 #endif // utility_SharingPtr_h_