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