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