]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[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
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();}
165
166     static SharingPtr<T> make_shared();
167
168     template<class A0>
169         static SharingPtr<T> make_shared(A0&);
170
171     template<class A0, class A1>
172         static SharingPtr<T> make_shared(A0&, A1&);
173
174     template<class A0, class A1, class A2>
175         static SharingPtr<T> make_shared(A0&, A1&, A2&);
176
177     template<class A0, class A1, class A2, class A3>
178         static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
179
180     template<class A0, class A1, class A2, class A3, class A4>
181         static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
182
183 private:
184
185     template <class U> friend class SharingPtr;
186 };
187
188 template<class T>
189 inline
190 SharingPtr<T>::SharingPtr()
191     : ptr_(0),
192       cntrl_(0)
193 {
194 }
195     
196 template<class T>
197 inline
198 SharingPtr<T>::SharingPtr(std::nullptr_t)
199 : ptr_(0),
200 cntrl_(0)
201 {
202 }
203
204 template<class T>
205 template<class Y>
206 SharingPtr<T>::SharingPtr(Y* p)
207     : ptr_(p), cntrl_(0)
208 {
209     std::unique_ptr<Y> hold(p);
210     typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
211     cntrl_ = new _CntrlBlk(p);
212     hold.release();
213 }
214
215 template<class T>
216 template<class Y>
217 SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
218     : ptr_(p), cntrl_(cntrl_block)
219 {
220 }
221
222 template<class T>
223 template<class Y>
224 inline
225 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
226     : ptr_(p),
227       cntrl_(r.cntrl_)
228 {
229     if (cntrl_)
230         cntrl_->add_shared();
231 }
232
233 template<class T>
234 inline
235 SharingPtr<T>::SharingPtr(const SharingPtr& r)
236     : ptr_(r.ptr_),
237       cntrl_(r.cntrl_)
238 {
239     if (cntrl_)
240         cntrl_->add_shared();
241 }
242
243 template<class T>
244 template<class Y>
245 inline
246 SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
247     : ptr_(r.ptr_),
248       cntrl_(r.cntrl_)
249 {
250     if (cntrl_)
251         cntrl_->add_shared();
252 }
253
254 template<class T>
255 SharingPtr<T>::~SharingPtr()
256 {
257     if (cntrl_)
258         cntrl_->release_shared();
259 }
260
261 template<class T>
262 inline
263 SharingPtr<T>&
264 SharingPtr<T>::operator=(const SharingPtr& r)
265 {
266     SharingPtr(r).swap(*this);
267     return *this;
268 }
269
270 template<class T>
271 template<class Y>
272 inline
273 SharingPtr<T>&
274 SharingPtr<T>::operator=(const SharingPtr<Y>& r)
275 {
276     SharingPtr(r).swap(*this);
277     return *this;
278 }
279
280 template<class T>
281 inline
282 void
283 SharingPtr<T>::swap(SharingPtr& r)
284 {
285     std::swap(ptr_, r.ptr_);
286     std::swap(cntrl_, r.cntrl_);
287 }
288
289 template<class T>
290 inline
291 void
292 SharingPtr<T>::reset()
293 {
294     SharingPtr().swap(*this);
295 }
296
297 template<class T>
298 template<class Y>
299 inline
300 void
301 SharingPtr<T>::reset(Y* p)
302 {
303     SharingPtr(p).swap(*this);
304 }
305
306 template<class T>
307 SharingPtr<T>
308 SharingPtr<T>::make_shared()
309 {
310     typedef imp::shared_ptr_emplace<T> CntrlBlk;
311     SharingPtr<T> r;
312     r.cntrl_ = new CntrlBlk();
313     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
314     return r;
315 }
316
317 template<class T>
318 template<class A0>
319 SharingPtr<T>
320 SharingPtr<T>::make_shared(A0& a0)
321 {
322     typedef imp::shared_ptr_emplace<T> CntrlBlk;
323     SharingPtr<T> r;
324     r.cntrl_ = new CntrlBlk(a0);
325     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
326     return r;
327 }
328
329 template<class T>
330 template<class A0, class A1>
331 SharingPtr<T>
332 SharingPtr<T>::make_shared(A0& a0, A1& a1)
333 {
334     typedef imp::shared_ptr_emplace<T> CntrlBlk;
335     SharingPtr<T> r;
336     r.cntrl_ = new CntrlBlk(a0, a1);
337     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
338     return r;
339 }
340
341 template<class T>
342 template<class A0, class A1, class A2>
343 SharingPtr<T>
344 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
345 {
346     typedef imp::shared_ptr_emplace<T> CntrlBlk;
347     SharingPtr<T> r;
348     r.cntrl_ = new CntrlBlk(a0, a1, a2);
349     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
350     return r;
351 }
352
353 template<class T>
354 template<class A0, class A1, class A2, class A3>
355 SharingPtr<T>
356 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
357 {
358     typedef imp::shared_ptr_emplace<T> CntrlBlk;
359     SharingPtr<T> r;
360     r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
361     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
362     return r;
363 }
364
365 template<class T>
366 template<class A0, class A1, class A2, class A3, class A4>
367 SharingPtr<T>
368 SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
369 {
370     typedef imp::shared_ptr_emplace<T> CntrlBlk;
371     SharingPtr<T> r;
372     r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
373     r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
374     return r;
375 }
376
377 template<class T>
378 inline
379 SharingPtr<T>
380 make_shared()
381 {
382     return SharingPtr<T>::make_shared();
383 }
384
385 template<class T, class A0>
386 inline
387 SharingPtr<T>
388 make_shared(A0& a0)
389 {
390     return SharingPtr<T>::make_shared(a0);
391 }
392
393 template<class T, class A0, class A1>
394 inline
395 SharingPtr<T>
396 make_shared(A0& a0, A1& a1)
397 {
398     return SharingPtr<T>::make_shared(a0, a1);
399 }
400
401 template<class T, class A0, class A1, class A2>
402 inline
403 SharingPtr<T>
404 make_shared(A0& a0, A1& a1, A2& a2)
405 {
406     return SharingPtr<T>::make_shared(a0, a1, a2);
407 }
408
409 template<class T, class A0, class A1, class A2, class A3>
410 inline
411 SharingPtr<T>
412 make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
413 {
414     return SharingPtr<T>::make_shared(a0, a1, a2, a3);
415 }
416
417 template<class T, class A0, class A1, class A2, class A3, class A4>
418 inline
419 SharingPtr<T>
420 make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
421 {
422     return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
423 }
424
425
426 template<class T, class U>
427 inline
428 bool
429 operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
430 {
431     return __x.get() == __y.get();
432 }
433
434 template<class T, class U>
435 inline
436 bool
437 operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
438 {
439     return !(__x == __y);
440 }
441
442 template<class T, class U>
443 inline
444 bool
445 operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
446 {
447     return __x.get() < __y.get();
448 }
449
450 template<class T>
451 inline
452 void
453 swap(SharingPtr<T>& __x, SharingPtr<T>& __y)
454 {
455     __x.swap(__y);
456 }
457
458 template<class T, class U>
459 inline
460 SharingPtr<T>
461 static_pointer_cast(const SharingPtr<U>& r)
462 {
463     return SharingPtr<T>(r, static_cast<T*>(r.get()));
464 }
465
466 template<class T, class U>
467 SharingPtr<T>
468 const_pointer_cast(const SharingPtr<U>& r)
469 {
470     return SharingPtr<T>(r, const_cast<T*>(r.get()));
471 }
472
473 template <class T>
474 class LoggingSharingPtr
475     : public SharingPtr<T>
476 {
477     typedef SharingPtr<T> base;
478
479 public:
480     typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
481     // action:  false means increment just happened
482     //          true  means decrement is about to happen
483
484 private:
485     Callback cb_;
486     void* baton_;
487
488 public:
489     LoggingSharingPtr() : cb_(0), baton_(0) {}
490     LoggingSharingPtr(Callback cb, void* baton)
491         : cb_(cb), baton_(baton)
492     {
493         if (cb_)
494             cb_(baton_, *this, false);
495     }
496
497     template <class Y>
498     LoggingSharingPtr(Y* p)
499         : base(p), cb_(0), baton_(0) {}
500
501     template <class Y>
502     LoggingSharingPtr(Y* p, Callback cb, void* baton)
503         : base(p), cb_(cb), baton_(baton)
504     {
505         if (cb_)
506             cb_(baton_, *this, false);
507     }
508
509     ~LoggingSharingPtr()
510     {
511         if (cb_)
512             cb_(baton_, *this, true);
513     }
514
515     LoggingSharingPtr(const LoggingSharingPtr& p)
516         : base(p), cb_(p.cb_), baton_(p.baton_)
517     {
518         if (cb_)
519             cb_(baton_, *this, false);
520     }
521
522     LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
523     {
524         if (cb_)
525             cb_(baton_, *this, true);
526         base::operator=(p);
527         cb_ = p.cb_;
528         baton_ = p.baton_;
529         if (cb_)
530             cb_(baton_, *this, false);
531         return *this;
532     }
533
534     void reset()
535     {
536         if (cb_)
537             cb_(baton_, *this, true);
538         base::reset();
539     }
540
541     template <class Y>
542     void reset(Y* p)
543     {
544         if (cb_)
545             cb_(baton_, *this, true);
546         base::reset(p);
547         if (cb_)
548             cb_(baton_, *this, false);
549     }
550
551     void SetCallback(Callback cb, void* baton)
552     {
553         cb_ = cb;
554         baton_ = baton;
555     }
556
557     void ClearCallback()
558     {
559         cb_ = 0;
560         baton_ = 0;
561     }
562 };
563     
564     
565 template <class T>
566 class IntrusiveSharingPtr;
567
568 template <class T>
569 class ReferenceCountedBase
570 {
571 public:
572     explicit ReferenceCountedBase()
573         : shared_owners_(-1) 
574     {
575     }
576     
577     void
578     add_shared();
579
580     void
581     release_shared();
582
583     long 
584     use_count() const 
585     {
586         return shared_owners_ + 1;
587     }
588     
589 protected:
590     long shared_owners_;
591    
592     friend class IntrusiveSharingPtr<T>;
593     
594 private:
595     ReferenceCountedBase(const ReferenceCountedBase&);
596     ReferenceCountedBase& operator=(const ReferenceCountedBase&);
597 };
598
599     template <class T>
600     void
601     lldb_private::ReferenceCountedBase<T>::add_shared()
602     {
603 #ifdef _MSC_VER
604         _InterlockedIncrement(&shared_owners_);
605 #else
606         ++shared_owners_;
607 #endif
608     }
609     
610     template <class T>
611     void
612     lldb_private::ReferenceCountedBase<T>::release_shared()
613     {
614 #ifdef _MSC_VER
615         if (_InterlockedDecrement(&shared_owners_) == -1)
616 #else
617         if (--shared_owners_ == -1)
618 #endif
619             delete static_cast<T*>(this);
620     }
621
622     
623 template <class T>
624 class ReferenceCountedBaseVirtual : public imp::shared_count
625 {
626 public:
627     explicit ReferenceCountedBaseVirtual () : 
628         imp::shared_count(-1)
629     {
630     }
631     
632     virtual
633     ~ReferenceCountedBaseVirtual ()
634     {
635     }
636     
637     virtual void on_zero_shared ();
638     
639 };
640
641 template <class T>
642 void
643 ReferenceCountedBaseVirtual<T>::on_zero_shared()
644 {
645 }
646
647 template <typename T>
648 class IntrusiveSharingPtr 
649 {
650 public:
651     typedef T element_type;
652     
653     explicit 
654     IntrusiveSharingPtr () : 
655         ptr_(0) 
656     {
657     }
658     
659     explicit
660     IntrusiveSharingPtr (T* ptr) : 
661         ptr_(ptr) 
662     {
663         add_shared();
664     }
665     
666     IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) : 
667         ptr_(rhs.ptr_) 
668     {
669         add_shared();
670     }
671     
672     template <class X>
673     IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
674         : ptr_(rhs.get()) 
675     {
676         add_shared();
677     }
678     
679     IntrusiveSharingPtr& 
680     operator= (const IntrusiveSharingPtr& rhs) 
681     {
682         reset(rhs.get());
683         return *this;
684     }
685     
686     template <class X> IntrusiveSharingPtr& 
687     operator= (const IntrusiveSharingPtr<X>& rhs) 
688     {
689         reset(rhs.get());
690         return *this;
691     }
692     
693     IntrusiveSharingPtr& 
694     operator= (T *ptr) 
695     {
696         reset(ptr);
697         return *this;
698     }
699     
700     ~IntrusiveSharingPtr() 
701     {
702         release_shared(); 
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
709         // issues.
710         ptr_ = NULL; 
711 #endif  // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
712     }
713     
714     T& 
715     operator*() const 
716     {
717         return *ptr_; 
718     }
719     
720     T* 
721     operator->() const
722     {
723         return ptr_; 
724     }
725     
726     T* 
727     get() const
728     {
729         return ptr_; 
730     }
731     
732     explicit operator bool() const
733     {
734         return ptr_ != 0;
735     }
736     
737     void 
738     swap (IntrusiveSharingPtr& rhs) 
739     {
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());
744 #endif
745     }
746
747     void 
748     reset(T* ptr = NULL) 
749     {
750         IntrusiveSharingPtr(ptr).swap(*this);
751     }
752
753     long
754     use_count () const
755     {
756         if (ptr_)
757             return ptr_->use_count();
758         return 0;
759     }
760     
761     bool
762     unique () const
763     {
764         return use_count () == 1;
765     }
766
767 private:
768     element_type *ptr_;
769     
770     void
771     add_shared() 
772     {
773         if (ptr_) 
774         {
775             ptr_->add_shared(); 
776 #if defined (ENABLE_SP_LOGGING)
777             track_sp (this, ptr_, ptr_->use_count());
778 #endif
779         }
780     }
781     void
782     release_shared()
783     { 
784         if (ptr_) 
785         {
786 #if defined (ENABLE_SP_LOGGING)
787             track_sp (this, NULL, ptr_->use_count() - 1);
788 #endif
789             ptr_->release_shared(); 
790         }
791     }
792 };
793
794 template<class T, class U>
795 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
796 {
797     return lhs.get() == rhs.get();
798 }
799
800 template<class T, class U>
801 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
802 {
803     return lhs.get() != rhs.get();
804 }
805
806 template<class T, class U>
807 inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
808 {
809     return lhs.get() == rhs;
810 }
811
812 template<class T, class U>
813 inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
814 {
815     return lhs.get() != rhs;
816 }
817
818 template<class T, class U>
819 inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
820 {
821     return lhs == rhs.get();
822 }
823
824 template<class T, class U>
825 inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
826 {
827     return lhs != rhs.get();
828 }
829
830 } // namespace lldb_private
831
832 #endif  // utility_SharingPtr_h_