]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
Update llvm, clang and lldb to 3.7.0 release.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Utility / SharingPtr.h
1 //===---------------------SharingPtr.h --------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef utility_SharingPtr_h_
11 #define utility_SharingPtr_h_
12
13 #include <algorithm>
14 #include <memory>
15
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
19 #ifdef _MSC_VER
20 #include <intrin.h>
21 #else
22 #include <atomic>
23 #endif
24
25 //#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
26 #if defined (ENABLE_SP_LOGGING)
27
28 extern "C" void track_sp (void *sp_this, void *ptr, long count);
29
30 #endif
31
32 namespace lldb_private {
33
34 namespace imp {
35     
36 class shared_count
37 {
38     shared_count(const shared_count&);
39     shared_count& operator=(const shared_count&);
40
41 protected:
42 #ifdef _MSC_VER
43     long shared_owners_;
44 #else
45     std::atomic<long> shared_owners_;
46 #endif
47     virtual ~shared_count();
48 private:
49     virtual void on_zero_shared() = 0;
50
51 public:
52     explicit shared_count(long refs = 0)
53         : shared_owners_(refs) {}
54
55     void add_shared();
56     void release_shared();
57     long use_count() const {return shared_owners_ + 1;}
58 };
59
60 template <class T>
61 class shared_ptr_pointer
62     : public shared_count
63 {
64     T data_;
65 public:
66     shared_ptr_pointer(T p)
67         :  data_(p) {}
68
69 private:
70     virtual void on_zero_shared();
71
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 &);
76 };
77
78 template <class T>
79 void
80 shared_ptr_pointer<T>::on_zero_shared()
81 {
82     delete data_;
83 }
84
85 template <class T>
86 class shared_ptr_emplace
87     : public shared_count
88 {
89     T data_;
90 public:
91
92     shared_ptr_emplace()
93         :  data_() {}
94
95     template <class A0>
96         shared_ptr_emplace(A0& a0)
97             :  data_(a0) {}
98
99     template <class A0, class A1>
100         shared_ptr_emplace(A0& a0, A1& a1)
101             :  data_(a0, a1) {}
102
103     template <class A0, class A1, class A2>
104         shared_ptr_emplace(A0& a0, A1& a1, A2& a2)
105             :  data_(a0, a1, a2) {}
106
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) {}
110
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) {}
114
115 private:
116     virtual void on_zero_shared();
117 public:
118     T* get() {return &data_;}
119 };
120
121 template <class T>
122 void
123 shared_ptr_emplace<T>::on_zero_shared()
124 {
125 }
126
127 }  // namespace
128
129 template<class T>
130 class SharingPtr
131 {
132 public: 
133     typedef T element_type; 
134 private:
135     element_type*      ptr_;
136     imp::shared_count* cntrl_;
137
138     struct nat {int for_bool_;};
139 public:
140     SharingPtr();
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);
146     template<class Y>
147         SharingPtr(const SharingPtr<Y>& r);
148
149     ~SharingPtr();
150
151     SharingPtr& operator=(const SharingPtr& r); 
152     template<class Y> SharingPtr& operator=(const SharingPtr<Y>& r); 
153
154     void swap(SharingPtr& r);
155     void reset();
156     template<class Y> void reset(Y* p);
157     void reset(std::nullptr_t);
158
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();}
166
167     static SharingPtr<T> make_shared();
168
169     template<class A0>
170         static SharingPtr<T> make_shared(A0&);
171
172     template<class A0, class A1>
173         static SharingPtr<T> make_shared(A0&, A1&);
174
175     template<class A0, class A1, class A2>
176         static SharingPtr<T> make_shared(A0&, A1&, A2&);
177
178     template<class A0, class A1, class A2, class A3>
179         static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
180
181     template<class A0, class A1, class A2, class A3, class A4>
182         static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
183
184 private:
185
186     template <class U> friend class SharingPtr;
187 };
188
189 template<class T>
190 inline
191 SharingPtr<T>::SharingPtr()
192     : ptr_(0),
193       cntrl_(0)
194 {
195 }
196     
197 template<class T>
198 inline
199 SharingPtr<T>::SharingPtr(std::nullptr_t)
200 : ptr_(0),
201 cntrl_(0)
202 {
203 }
204
205 template<class T>
206 template<class Y>
207 SharingPtr<T>::SharingPtr(Y* p)
208     : ptr_(p), cntrl_(0)
209 {
210     std::unique_ptr<Y> hold(p);
211     typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
212     cntrl_ = new _CntrlBlk(p);
213     hold.release();
214 }
215
216 template<class T>
217 template<class Y>
218 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
219     : ptr_(p), cntrl_(cntrl_block)
220 {
221 }
222
223 template<class T>
224 template<class Y>
225 inline
226 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
227     : ptr_(p),
228       cntrl_(r.cntrl_)
229 {
230     if (cntrl_)
231         cntrl_->add_shared();
232 }
233
234 template<class T>
235 inline
236 SharingPtr<T>::SharingPtr(const SharingPtr& r)
237     : ptr_(r.ptr_),
238       cntrl_(r.cntrl_)
239 {
240     if (cntrl_)
241         cntrl_->add_shared();
242 }
243
244 template<class T>
245 template<class Y>
246 inline
247 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
248     : ptr_(r.ptr_),
249       cntrl_(r.cntrl_)
250 {
251     if (cntrl_)
252         cntrl_->add_shared();
253 }
254
255 template<class T>
256 SharingPtr<T>::~SharingPtr()
257 {
258     if (cntrl_)
259         cntrl_->release_shared();
260 }
261
262 template<class T>
263 inline
264 SharingPtr<T>&
265 SharingPtr<T>::operator=(const SharingPtr& r)
266 {
267     SharingPtr(r).swap(*this);
268     return *this;
269 }
270
271 template<class T>
272 template<class Y>
273 inline
274 SharingPtr<T>&
275 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
276 {
277     SharingPtr(r).swap(*this);
278     return *this;
279 }
280
281 template<class T>
282 inline
283 void
284 SharingPtr<T>::swap(SharingPtr& r)
285 {
286     std::swap(ptr_, r.ptr_);
287     std::swap(cntrl_, r.cntrl_);
288 }
289
290 template<class T>
291 inline
292 void
293 SharingPtr<T>::reset()
294 {
295     SharingPtr().swap(*this);
296 }
297
298 template<class T>
299 inline
300 void
301 SharingPtr<T>::reset (std::nullptr_t p)
302 {
303     reset();
304 }
305     
306 template<class T>
307 template<class Y>
308 inline
309 void
310 SharingPtr<T>::reset(Y* p)
311 {
312     SharingPtr(p).swap(*this);
313 }
314
315 template<class T>
316 SharingPtr<T>
317 SharingPtr<T>::make_shared()
318 {
319     typedef imp::shared_ptr_emplace<T> CntrlBlk;
320     SharingPtr<T> r;
321     r.cntrl_ = new CntrlBlk();
322     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
323     return r;
324 }
325
326 template<class T>
327 template<class A0>
328 SharingPtr<T>
329 SharingPtr<T>::make_shared(A0& a0)
330 {
331     typedef imp::shared_ptr_emplace<T> CntrlBlk;
332     SharingPtr<T> r;
333     r.cntrl_ = new CntrlBlk(a0);
334     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
335     return r;
336 }
337
338 template<class T>
339 template<class A0, class A1>
340 SharingPtr<T>
341 SharingPtr<T>::make_shared(A0& a0, A1& a1)
342 {
343     typedef imp::shared_ptr_emplace<T> CntrlBlk;
344     SharingPtr<T> r;
345     r.cntrl_ = new CntrlBlk(a0, a1);
346     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
347     return r;
348 }
349
350 template<class T>
351 template<class A0, class A1, class A2>
352 SharingPtr<T>
353 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
354 {
355     typedef imp::shared_ptr_emplace<T> CntrlBlk;
356     SharingPtr<T> r;
357     r.cntrl_ = new CntrlBlk(a0, a1, a2);
358     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
359     return r;
360 }
361
362 template<class T>
363 template<class A0, class A1, class A2, class A3>
364 SharingPtr<T>
365 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
366 {
367     typedef imp::shared_ptr_emplace<T> CntrlBlk;
368     SharingPtr<T> r;
369     r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
370     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
371     return r;
372 }
373
374 template<class T>
375 template<class A0, class A1, class A2, class A3, class A4>
376 SharingPtr<T>
377 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
378 {
379     typedef imp::shared_ptr_emplace<T> CntrlBlk;
380     SharingPtr<T> r;
381     r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
382     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
383     return r;
384 }
385
386 template<class T>
387 inline
388 SharingPtr<T>
389 make_shared()
390 {
391     return SharingPtr<T>::make_shared();
392 }
393
394 template<class T, class A0>
395 inline
396 SharingPtr<T>
397 make_shared(A0& a0)
398 {
399     return SharingPtr<T>::make_shared(a0);
400 }
401
402 template<class T, class A0, class A1>
403 inline
404 SharingPtr<T>
405 make_shared(A0& a0, A1& a1)
406 {
407     return SharingPtr<T>::make_shared(a0, a1);
408 }
409
410 template<class T, class A0, class A1, class A2>
411 inline
412 SharingPtr<T>
413 make_shared(A0& a0, A1& a1, A2& a2)
414 {
415     return SharingPtr<T>::make_shared(a0, a1, a2);
416 }
417
418 template<class T, class A0, class A1, class A2, class A3>
419 inline
420 SharingPtr<T>
421 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
422 {
423     return SharingPtr<T>::make_shared(a0, a1, a2, a3);
424 }
425
426 template<class T, class A0, class A1, class A2, class A3, class A4>
427 inline
428 SharingPtr<T>
429 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
430 {
431     return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
432 }
433
434
435 template<class T, class U>
436 inline
437 bool
438 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
439 {
440     return __x.get() == __y.get();
441 }
442
443 template<class T, class U>
444 inline
445 bool
446 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
447 {
448     return !(__x == __y);
449 }
450
451 template<class T, class U>
452 inline
453 bool
454 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
455 {
456     return __x.get() < __y.get();
457 }
458
459 template<class T>
460 inline
461 void
462 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
463 {
464     __x.swap(__y);
465 }
466
467 template<class T, class U>
468 inline
469 SharingPtr<T>
470 static_pointer_cast(const SharingPtr<U>& r)
471 {
472     return SharingPtr<T>(r, static_cast<T*>(r.get()));
473 }
474
475 template<class T, class U>
476 SharingPtr<T>
477 const_pointer_cast(const SharingPtr<U>& r)
478 {
479     return SharingPtr<T>(r, const_cast<T*>(r.get()));
480 }
481
482 template <class T>
483 class LoggingSharingPtr
484     : public SharingPtr<T>
485 {
486     typedef SharingPtr<T> base;
487
488 public:
489     typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
490     // action:  false means increment just happened
491     //          true  means decrement is about to happen
492
493 private:
494     Callback cb_;
495     void* baton_;
496
497 public:
498     LoggingSharingPtr() : cb_(0), baton_(0) {}
499     LoggingSharingPtr(Callback cb, void* baton)
500         : cb_(cb), baton_(baton)
501     {
502         if (cb_)
503             cb_(baton_, *this, false);
504     }
505
506     template <class Y>
507     LoggingSharingPtr(Y* p)
508         : base(p), cb_(0), baton_(0) {}
509
510     template <class Y>
511     LoggingSharingPtr(Y* p, Callback cb, void* baton)
512         : base(p), cb_(cb), baton_(baton)
513     {
514         if (cb_)
515             cb_(baton_, *this, false);
516     }
517
518     ~LoggingSharingPtr()
519     {
520         if (cb_)
521             cb_(baton_, *this, true);
522     }
523
524     LoggingSharingPtr(const LoggingSharingPtr& p)
525         : base(p), cb_(p.cb_), baton_(p.baton_)
526     {
527         if (cb_)
528             cb_(baton_, *this, false);
529     }
530
531     LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
532     {
533         if (cb_)
534             cb_(baton_, *this, true);
535         base::operator=(p);
536         cb_ = p.cb_;
537         baton_ = p.baton_;
538         if (cb_)
539             cb_(baton_, *this, false);
540         return *this;
541     }
542
543     void reset()
544     {
545         if (cb_)
546             cb_(baton_, *this, true);
547         base::reset();
548     }
549
550     template <class Y>
551     void reset(Y* p)
552     {
553         if (cb_)
554             cb_(baton_, *this, true);
555         base::reset(p);
556         if (cb_)
557             cb_(baton_, *this, false);
558     }
559     
560     void SetCallback(Callback cb, void* baton)
561     {
562         cb_ = cb;
563         baton_ = baton;
564     }
565
566     void ClearCallback()
567     {
568         cb_ = 0;
569         baton_ = 0;
570     }
571 };
572     
573     
574 template <class T>
575 class IntrusiveSharingPtr;
576
577 template <class T>
578 class ReferenceCountedBase
579 {
580 public:
581     explicit ReferenceCountedBase()
582         : shared_owners_(-1) 
583     {
584     }
585     
586     void
587     add_shared();
588
589     void
590     release_shared();
591
592     long 
593     use_count() const 
594     {
595         return shared_owners_ + 1;
596     }
597     
598 protected:
599     long shared_owners_;
600    
601     friend class IntrusiveSharingPtr<T>;
602     
603 private:
604     ReferenceCountedBase(const ReferenceCountedBase&);
605     ReferenceCountedBase& operator=(const ReferenceCountedBase&);
606 };
607
608     template <class T>
609     void
610     lldb_private::ReferenceCountedBase<T>::add_shared()
611     {
612 #ifdef _MSC_VER
613         _InterlockedIncrement(&shared_owners_);
614 #else
615         ++shared_owners_;
616 #endif
617     }
618     
619     template <class T>
620     void
621     lldb_private::ReferenceCountedBase<T>::release_shared()
622     {
623 #ifdef _MSC_VER
624         if (_InterlockedDecrement(&shared_owners_) == -1)
625 #else
626         if (--shared_owners_ == -1)
627 #endif
628             delete static_cast<T*>(this);
629     }
630
631     
632 template <class T>
633 class ReferenceCountedBaseVirtual : public imp::shared_count
634 {
635 public:
636     explicit ReferenceCountedBaseVirtual () : 
637         imp::shared_count(-1)
638     {
639     }
640     
641     virtual
642     ~ReferenceCountedBaseVirtual ()
643     {
644     }
645     
646     virtual void on_zero_shared ();
647     
648 };
649
650 template <class T>
651 void
652 ReferenceCountedBaseVirtual<T>::on_zero_shared()
653 {
654 }
655
656 template <typename T>
657 class IntrusiveSharingPtr 
658 {
659 public:
660     typedef T element_type;
661     
662     explicit 
663     IntrusiveSharingPtr () : 
664         ptr_(0) 
665     {
666     }
667     
668     explicit
669     IntrusiveSharingPtr (T* ptr) : 
670         ptr_(ptr) 
671     {
672         add_shared();
673     }
674     
675     IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) : 
676         ptr_(rhs.ptr_) 
677     {
678         add_shared();
679     }
680     
681     template <class X>
682     IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
683         : ptr_(rhs.get()) 
684     {
685         add_shared();
686     }
687     
688     IntrusiveSharingPtr& 
689     operator= (const IntrusiveSharingPtr& rhs) 
690     {
691         reset(rhs.get());
692         return *this;
693     }
694     
695     template <class X> IntrusiveSharingPtr& 
696     operator= (const IntrusiveSharingPtr<X>& rhs) 
697     {
698         reset(rhs.get());
699         return *this;
700     }
701     
702     IntrusiveSharingPtr& 
703     operator= (T *ptr) 
704     {
705         reset(ptr);
706         return *this;
707     }
708     
709     ~IntrusiveSharingPtr() 
710     {
711         release_shared(); 
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
718         // issues.
719         ptr_ = NULL; 
720 #endif  // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
721     }
722     
723     T& 
724     operator*() const 
725     {
726         return *ptr_; 
727     }
728     
729     T* 
730     operator->() const
731     {
732         return ptr_; 
733     }
734     
735     T* 
736     get() const
737     {
738         return ptr_; 
739     }
740     
741     explicit operator bool() const
742     {
743         return ptr_ != 0;
744     }
745     
746     void 
747     swap (IntrusiveSharingPtr& rhs) 
748     {
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());
753 #endif
754     }
755
756     void 
757     reset(T* ptr = NULL) 
758     {
759         IntrusiveSharingPtr(ptr).swap(*this);
760     }
761
762     long
763     use_count () const
764     {
765         if (ptr_)
766             return ptr_->use_count();
767         return 0;
768     }
769     
770     bool
771     unique () const
772     {
773         return use_count () == 1;
774     }
775
776 private:
777     element_type *ptr_;
778     
779     void
780     add_shared() 
781     {
782         if (ptr_) 
783         {
784             ptr_->add_shared(); 
785 #if defined (ENABLE_SP_LOGGING)
786             track_sp (this, ptr_, ptr_->use_count());
787 #endif
788         }
789     }
790     void
791     release_shared()
792     { 
793         if (ptr_) 
794         {
795 #if defined (ENABLE_SP_LOGGING)
796             track_sp (this, NULL, ptr_->use_count() - 1);
797 #endif
798             ptr_->release_shared(); 
799         }
800     }
801 };
802
803 template<class T, class U>
804 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
805 {
806     return lhs.get() == rhs.get();
807 }
808
809 template<class T, class U>
810 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
811 {
812     return lhs.get() != rhs.get();
813 }
814
815 template<class T, class U>
816 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
817 {
818     return lhs.get() == rhs;
819 }
820
821 template<class T, class U>
822 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
823 {
824     return lhs.get() != rhs;
825 }
826
827 template<class T, class U>
828 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
829 {
830     return lhs == rhs.get();
831 }
832
833 template<class T, class U>
834 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
835 {
836     return lhs != rhs.get();
837 }
838
839 } // namespace lldb_private
840
841 #endif  // utility_SharingPtr_h_