1254721Semaste//===---------------------SharingPtr.h --------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#ifndef utility_SharingPtr_h_
11254721Semaste#define utility_SharingPtr_h_
12254721Semaste
13254721Semaste#include <algorithm>
14254721Semaste#include <memory>
15254721Semaste
16263363Semaste// Microsoft Visual C++ currently does not enable std::atomic to work
17263363Semaste// in CLR mode - as such we need to "hack around it" for MSVC++ builds only
18263363Semaste// using Windows specific instrinsics instead of the C++11 atomic support
19263363Semaste#ifdef _MSC_VER
20263363Semaste#include <intrin.h>
21263363Semaste#else
22263363Semaste#include <atomic>
23263363Semaste#endif
24263363Semaste
25254721Semaste//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
26254721Semaste#if defined (ENABLE_SP_LOGGING)
27254721Semaste
28254721Semasteextern "C" void track_sp (void *sp_this, void *ptr, long count);
29254721Semaste
30254721Semaste#endif
31254721Semaste
32254721Semastenamespace lldb_private {
33254721Semaste
34254721Semastenamespace imp {
35254721Semaste
36254721Semasteclass shared_count
37254721Semaste{
38254721Semaste    shared_count(const shared_count&);
39254721Semaste    shared_count& operator=(const shared_count&);
40254721Semaste
41254721Semasteprotected:
42263363Semaste#ifdef _MSC_VER
43254721Semaste    long shared_owners_;
44263363Semaste#else
45263363Semaste    std::atomic<long> shared_owners_;
46263363Semaste#endif
47254721Semaste    virtual ~shared_count();
48254721Semasteprivate:
49254721Semaste    virtual void on_zero_shared() = 0;
50254721Semaste
51254721Semastepublic:
52254721Semaste    explicit shared_count(long refs = 0)
53254721Semaste        : shared_owners_(refs) {}
54254721Semaste
55254721Semaste    void add_shared();
56254721Semaste    void release_shared();
57254721Semaste    long use_count() const {return shared_owners_ + 1;}
58254721Semaste};
59254721Semaste
60254721Semastetemplate <class T>
61254721Semasteclass shared_ptr_pointer
62254721Semaste    : public shared_count
63254721Semaste{
64254721Semaste    T data_;
65254721Semastepublic:
66254721Semaste    shared_ptr_pointer(T p)
67254721Semaste        :  data_(p) {}
68254721Semaste
69254721Semasteprivate:
70254721Semaste    virtual void on_zero_shared();
71254721Semaste
72254721Semaste    // Outlaw copy constructor and assignment operator to keep effictive C++
73254721Semaste    // warnings down to a minumum
74254721Semaste    shared_ptr_pointer (const shared_ptr_pointer &);
75254721Semaste    shared_ptr_pointer & operator=(const shared_ptr_pointer &);
76254721Semaste};
77254721Semaste
78254721Semastetemplate <class T>
79254721Semastevoid
80254721Semasteshared_ptr_pointer<T>::on_zero_shared()
81254721Semaste{
82254721Semaste    delete data_;
83254721Semaste}
84254721Semaste
85254721Semastetemplate <class T>
86254721Semasteclass shared_ptr_emplace
87254721Semaste    : public shared_count
88254721Semaste{
89254721Semaste    T data_;
90254721Semastepublic:
91254721Semaste
92254721Semaste    shared_ptr_emplace()
93254721Semaste        :  data_() {}
94254721Semaste
95254721Semaste    template <class A0>
96254721Semaste        shared_ptr_emplace(A0& a0)
97254721Semaste            :  data_(a0) {}
98254721Semaste
99254721Semaste    template <class A0, class A1>
100254721Semaste        shared_ptr_emplace(A0& a0, A1& a1)
101254721Semaste            :  data_(a0, a1) {}
102254721Semaste
103254721Semaste    template <class A0, class A1, class A2>
104254721Semaste        shared_ptr_emplace(A0& a0, A1& a1, A2& a2)
105254721Semaste            :  data_(a0, a1, a2) {}
106254721Semaste
107254721Semaste    template <class A0, class A1, class A2, class A3>
108254721Semaste        shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3)
109254721Semaste            :  data_(a0, a1, a2, a3) {}
110254721Semaste
111254721Semaste    template <class A0, class A1, class A2, class A3, class A4>
112254721Semaste        shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
113254721Semaste            :  data_(a0, a1, a2, a3, a4) {}
114254721Semaste
115254721Semasteprivate:
116254721Semaste    virtual void on_zero_shared();
117254721Semastepublic:
118254721Semaste    T* get() {return &data_;}
119254721Semaste};
120254721Semaste
121254721Semastetemplate <class T>
122254721Semastevoid
123254721Semasteshared_ptr_emplace<T>::on_zero_shared()
124254721Semaste{
125254721Semaste}
126254721Semaste
127254721Semaste}  // namespace
128254721Semaste
129254721Semastetemplate<class T>
130254721Semasteclass SharingPtr
131254721Semaste{
132254721Semastepublic:
133254721Semaste    typedef T element_type;
134254721Semasteprivate:
135254721Semaste    element_type*      ptr_;
136254721Semaste    imp::shared_count* cntrl_;
137254721Semaste
138254721Semaste    struct nat {int for_bool_;};
139254721Semastepublic:
140254721Semaste    SharingPtr();
141254721Semaste    template<class Y> explicit SharingPtr(Y* p);
142254721Semaste    template<class Y> explicit SharingPtr(Y* p, imp::shared_count *ctrl_block);
143254721Semaste    template<class Y> SharingPtr(const SharingPtr<Y>& r, element_type *p);
144254721Semaste    SharingPtr(const SharingPtr& r);
145254721Semaste    template<class Y>
146254721Semaste        SharingPtr(const SharingPtr<Y>& r);
147254721Semaste
148254721Semaste    ~SharingPtr();
149254721Semaste
150254721Semaste    SharingPtr& operator=(const SharingPtr& r);
151254721Semaste    template<class Y> SharingPtr& operator=(const SharingPtr<Y>& r);
152254721Semaste
153254721Semaste    void swap(SharingPtr& r);
154254721Semaste    void reset();
155254721Semaste    template<class Y> void reset(Y* p);
156254721Semaste
157254721Semaste    element_type* get() const {return ptr_;}
158254721Semaste    element_type& operator*() const {return *ptr_;}
159254721Semaste    element_type* operator->() const {return ptr_;}
160254721Semaste    long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
161254721Semaste    bool unique() const {return use_count() == 1;}
162254721Semaste    bool empty() const {return cntrl_ == 0;}
163254721Semaste    operator nat*() const {return (nat*)get();}
164254721Semaste
165254721Semaste    static SharingPtr<T> make_shared();
166254721Semaste
167254721Semaste    template<class A0>
168254721Semaste        static SharingPtr<T> make_shared(A0&);
169254721Semaste
170254721Semaste    template<class A0, class A1>
171254721Semaste        static SharingPtr<T> make_shared(A0&, A1&);
172254721Semaste
173254721Semaste    template<class A0, class A1, class A2>
174254721Semaste        static SharingPtr<T> make_shared(A0&, A1&, A2&);
175254721Semaste
176254721Semaste    template<class A0, class A1, class A2, class A3>
177254721Semaste        static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&);
178254721Semaste
179254721Semaste    template<class A0, class A1, class A2, class A3, class A4>
180254721Semaste        static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
181254721Semaste
182254721Semasteprivate:
183254721Semaste
184254721Semaste    template <class U> friend class SharingPtr;
185254721Semaste};
186254721Semaste
187254721Semastetemplate<class T>
188254721Semasteinline
189254721SemasteSharingPtr<T>::SharingPtr()
190254721Semaste    : ptr_(0),
191254721Semaste      cntrl_(0)
192254721Semaste{
193254721Semaste}
194254721Semaste
195254721Semastetemplate<class T>
196254721Semastetemplate<class Y>
197254721SemasteSharingPtr<T>::SharingPtr(Y* p)
198254721Semaste    : ptr_(p), cntrl_(0)
199254721Semaste{
200254721Semaste    std::unique_ptr<Y> hold(p);
201254721Semaste    typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
202254721Semaste    cntrl_ = new _CntrlBlk(p);
203254721Semaste    hold.release();
204254721Semaste}
205254721Semaste
206254721Semastetemplate<class T>
207254721Semastetemplate<class Y>
208254721SemasteSharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block)
209254721Semaste    : ptr_(p), cntrl_(cntrl_block)
210254721Semaste{
211254721Semaste}
212254721Semaste
213254721Semastetemplate<class T>
214254721Semastetemplate<class Y>
215254721Semasteinline
216254721SemasteSharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p)
217254721Semaste    : ptr_(p),
218254721Semaste      cntrl_(r.cntrl_)
219254721Semaste{
220254721Semaste    if (cntrl_)
221254721Semaste        cntrl_->add_shared();
222254721Semaste}
223254721Semaste
224254721Semastetemplate<class T>
225254721Semasteinline
226254721SemasteSharingPtr<T>::SharingPtr(const SharingPtr& r)
227254721Semaste    : ptr_(r.ptr_),
228254721Semaste      cntrl_(r.cntrl_)
229254721Semaste{
230254721Semaste    if (cntrl_)
231254721Semaste        cntrl_->add_shared();
232254721Semaste}
233254721Semaste
234254721Semastetemplate<class T>
235254721Semastetemplate<class Y>
236254721Semasteinline
237254721SemasteSharingPtr<T>::SharingPtr(const SharingPtr<Y>& r)
238254721Semaste    : ptr_(r.ptr_),
239254721Semaste      cntrl_(r.cntrl_)
240254721Semaste{
241254721Semaste    if (cntrl_)
242254721Semaste        cntrl_->add_shared();
243254721Semaste}
244254721Semaste
245254721Semastetemplate<class T>
246254721SemasteSharingPtr<T>::~SharingPtr()
247254721Semaste{
248254721Semaste    if (cntrl_)
249254721Semaste        cntrl_->release_shared();
250254721Semaste}
251254721Semaste
252254721Semastetemplate<class T>
253254721Semasteinline
254254721SemasteSharingPtr<T>&
255254721SemasteSharingPtr<T>::operator=(const SharingPtr& r)
256254721Semaste{
257254721Semaste    SharingPtr(r).swap(*this);
258254721Semaste    return *this;
259254721Semaste}
260254721Semaste
261254721Semastetemplate<class T>
262254721Semastetemplate<class Y>
263254721Semasteinline
264254721SemasteSharingPtr<T>&
265254721SemasteSharingPtr<T>::operator=(const SharingPtr<Y>& r)
266254721Semaste{
267254721Semaste    SharingPtr(r).swap(*this);
268254721Semaste    return *this;
269254721Semaste}
270254721Semaste
271254721Semastetemplate<class T>
272254721Semasteinline
273254721Semastevoid
274254721SemasteSharingPtr<T>::swap(SharingPtr& r)
275254721Semaste{
276254721Semaste    std::swap(ptr_, r.ptr_);
277254721Semaste    std::swap(cntrl_, r.cntrl_);
278254721Semaste}
279254721Semaste
280254721Semastetemplate<class T>
281254721Semasteinline
282254721Semastevoid
283254721SemasteSharingPtr<T>::reset()
284254721Semaste{
285254721Semaste    SharingPtr().swap(*this);
286254721Semaste}
287254721Semaste
288254721Semastetemplate<class T>
289254721Semastetemplate<class Y>
290254721Semasteinline
291254721Semastevoid
292254721SemasteSharingPtr<T>::reset(Y* p)
293254721Semaste{
294254721Semaste    SharingPtr(p).swap(*this);
295254721Semaste}
296254721Semaste
297254721Semastetemplate<class T>
298254721SemasteSharingPtr<T>
299254721SemasteSharingPtr<T>::make_shared()
300254721Semaste{
301254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
302254721Semaste    SharingPtr<T> r;
303254721Semaste    r.cntrl_ = new CntrlBlk();
304254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
305254721Semaste    return r;
306254721Semaste}
307254721Semaste
308254721Semastetemplate<class T>
309254721Semastetemplate<class A0>
310254721SemasteSharingPtr<T>
311254721SemasteSharingPtr<T>::make_shared(A0& a0)
312254721Semaste{
313254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
314254721Semaste    SharingPtr<T> r;
315254721Semaste    r.cntrl_ = new CntrlBlk(a0);
316254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
317254721Semaste    return r;
318254721Semaste}
319254721Semaste
320254721Semastetemplate<class T>
321254721Semastetemplate<class A0, class A1>
322254721SemasteSharingPtr<T>
323254721SemasteSharingPtr<T>::make_shared(A0& a0, A1& a1)
324254721Semaste{
325254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
326254721Semaste    SharingPtr<T> r;
327254721Semaste    r.cntrl_ = new CntrlBlk(a0, a1);
328254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
329254721Semaste    return r;
330254721Semaste}
331254721Semaste
332254721Semastetemplate<class T>
333254721Semastetemplate<class A0, class A1, class A2>
334254721SemasteSharingPtr<T>
335254721SemasteSharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2)
336254721Semaste{
337254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
338254721Semaste    SharingPtr<T> r;
339254721Semaste    r.cntrl_ = new CntrlBlk(a0, a1, a2);
340254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
341254721Semaste    return r;
342254721Semaste}
343254721Semaste
344254721Semastetemplate<class T>
345254721Semastetemplate<class A0, class A1, class A2, class A3>
346254721SemasteSharingPtr<T>
347254721SemasteSharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3)
348254721Semaste{
349254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
350254721Semaste    SharingPtr<T> r;
351254721Semaste    r.cntrl_ = new CntrlBlk(a0, a1, a2, a3);
352254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
353254721Semaste    return r;
354254721Semaste}
355254721Semaste
356254721Semastetemplate<class T>
357254721Semastetemplate<class A0, class A1, class A2, class A3, class A4>
358254721SemasteSharingPtr<T>
359254721SemasteSharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
360254721Semaste{
361254721Semaste    typedef imp::shared_ptr_emplace<T> CntrlBlk;
362254721Semaste    SharingPtr<T> r;
363254721Semaste    r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4);
364254721Semaste    r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get();
365254721Semaste    return r;
366254721Semaste}
367254721Semaste
368254721Semastetemplate<class T>
369254721Semasteinline
370254721SemasteSharingPtr<T>
371254721Semastemake_shared()
372254721Semaste{
373254721Semaste    return SharingPtr<T>::make_shared();
374254721Semaste}
375254721Semaste
376254721Semastetemplate<class T, class A0>
377254721Semasteinline
378254721SemasteSharingPtr<T>
379254721Semastemake_shared(A0& a0)
380254721Semaste{
381254721Semaste    return SharingPtr<T>::make_shared(a0);
382254721Semaste}
383254721Semaste
384254721Semastetemplate<class T, class A0, class A1>
385254721Semasteinline
386254721SemasteSharingPtr<T>
387254721Semastemake_shared(A0& a0, A1& a1)
388254721Semaste{
389254721Semaste    return SharingPtr<T>::make_shared(a0, a1);
390254721Semaste}
391254721Semaste
392254721Semastetemplate<class T, class A0, class A1, class A2>
393254721Semasteinline
394254721SemasteSharingPtr<T>
395254721Semastemake_shared(A0& a0, A1& a1, A2& a2)
396254721Semaste{
397254721Semaste    return SharingPtr<T>::make_shared(a0, a1, a2);
398254721Semaste}
399254721Semaste
400254721Semastetemplate<class T, class A0, class A1, class A2, class A3>
401254721Semasteinline
402254721SemasteSharingPtr<T>
403254721Semastemake_shared(A0& a0, A1& a1, A2& a2, A3& a3)
404254721Semaste{
405254721Semaste    return SharingPtr<T>::make_shared(a0, a1, a2, a3);
406254721Semaste}
407254721Semaste
408254721Semastetemplate<class T, class A0, class A1, class A2, class A3, class A4>
409254721Semasteinline
410254721SemasteSharingPtr<T>
411254721Semastemake_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
412254721Semaste{
413254721Semaste    return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
414254721Semaste}
415254721Semaste
416254721Semaste
417254721Semastetemplate<class T, class U>
418254721Semasteinline
419254721Semastebool
420254721Semasteoperator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
421254721Semaste{
422254721Semaste    return __x.get() == __y.get();
423254721Semaste}
424254721Semaste
425254721Semastetemplate<class T, class U>
426254721Semasteinline
427254721Semastebool
428254721Semasteoperator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
429254721Semaste{
430254721Semaste    return !(__x == __y);
431254721Semaste}
432254721Semaste
433254721Semastetemplate<class T, class U>
434254721Semasteinline
435254721Semastebool
436254721Semasteoperator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y)
437254721Semaste{
438254721Semaste    return __x.get() < __y.get();
439254721Semaste}
440254721Semaste
441254721Semastetemplate<class T>
442254721Semasteinline
443254721Semastevoid
444254721Semasteswap(SharingPtr<T>& __x, SharingPtr<T>& __y)
445254721Semaste{
446254721Semaste    __x.swap(__y);
447254721Semaste}
448254721Semaste
449254721Semastetemplate<class T, class U>
450254721Semasteinline
451254721SemasteSharingPtr<T>
452254721Semastestatic_pointer_cast(const SharingPtr<U>& r)
453254721Semaste{
454254721Semaste    return SharingPtr<T>(r, static_cast<T*>(r.get()));
455254721Semaste}
456254721Semaste
457254721Semastetemplate<class T, class U>
458254721SemasteSharingPtr<T>
459254721Semasteconst_pointer_cast(const SharingPtr<U>& r)
460254721Semaste{
461254721Semaste    return SharingPtr<T>(r, const_cast<T*>(r.get()));
462254721Semaste}
463254721Semaste
464254721Semastetemplate <class T>
465254721Semasteclass LoggingSharingPtr
466254721Semaste    : public SharingPtr<T>
467254721Semaste{
468254721Semaste    typedef SharingPtr<T> base;
469254721Semaste
470254721Semastepublic:
471254721Semaste    typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action);
472254721Semaste    // action:  false means increment just happened
473254721Semaste    //          true  means decrement is about to happen
474254721Semaste
475254721Semasteprivate:
476254721Semaste    Callback cb_;
477254721Semaste    void* baton_;
478254721Semaste
479254721Semastepublic:
480254721Semaste    LoggingSharingPtr() : cb_(0), baton_(0) {}
481254721Semaste    LoggingSharingPtr(Callback cb, void* baton)
482254721Semaste        : cb_(cb), baton_(baton)
483254721Semaste    {
484254721Semaste        if (cb_)
485254721Semaste            cb_(baton_, *this, false);
486254721Semaste    }
487254721Semaste
488254721Semaste    template <class Y>
489254721Semaste    LoggingSharingPtr(Y* p)
490254721Semaste        : base(p), cb_(0), baton_(0) {}
491254721Semaste
492254721Semaste    template <class Y>
493254721Semaste    LoggingSharingPtr(Y* p, Callback cb, void* baton)
494254721Semaste        : base(p), cb_(cb), baton_(baton)
495254721Semaste    {
496254721Semaste        if (cb_)
497254721Semaste            cb_(baton_, *this, false);
498254721Semaste    }
499254721Semaste
500254721Semaste    ~LoggingSharingPtr()
501254721Semaste    {
502254721Semaste        if (cb_)
503254721Semaste            cb_(baton_, *this, true);
504254721Semaste    }
505254721Semaste
506254721Semaste    LoggingSharingPtr(const LoggingSharingPtr& p)
507254721Semaste        : base(p), cb_(p.cb_), baton_(p.baton_)
508254721Semaste    {
509254721Semaste        if (cb_)
510254721Semaste            cb_(baton_, *this, false);
511254721Semaste    }
512254721Semaste
513254721Semaste    LoggingSharingPtr& operator=(const LoggingSharingPtr& p)
514254721Semaste    {
515254721Semaste        if (cb_)
516254721Semaste            cb_(baton_, *this, true);
517254721Semaste        base::operator=(p);
518254721Semaste        cb_ = p.cb_;
519254721Semaste        baton_ = p.baton_;
520254721Semaste        if (cb_)
521254721Semaste            cb_(baton_, *this, false);
522254721Semaste        return *this;
523254721Semaste    }
524254721Semaste
525254721Semaste    void reset()
526254721Semaste    {
527254721Semaste        if (cb_)
528254721Semaste            cb_(baton_, *this, true);
529254721Semaste        base::reset();
530254721Semaste    }
531254721Semaste
532254721Semaste    template <class Y>
533254721Semaste    void reset(Y* p)
534254721Semaste    {
535254721Semaste        if (cb_)
536254721Semaste            cb_(baton_, *this, true);
537254721Semaste        base::reset(p);
538254721Semaste        if (cb_)
539254721Semaste            cb_(baton_, *this, false);
540254721Semaste    }
541254721Semaste
542254721Semaste    void SetCallback(Callback cb, void* baton)
543254721Semaste    {
544254721Semaste        cb_ = cb;
545254721Semaste        baton_ = baton;
546254721Semaste    }
547254721Semaste
548254721Semaste    void ClearCallback()
549254721Semaste    {
550254721Semaste        cb_ = 0;
551254721Semaste        baton_ = 0;
552254721Semaste    }
553254721Semaste};
554254721Semaste
555254721Semaste
556254721Semastetemplate <class T>
557254721Semasteclass IntrusiveSharingPtr;
558254721Semaste
559254721Semastetemplate <class T>
560254721Semasteclass ReferenceCountedBase
561254721Semaste{
562254721Semastepublic:
563254721Semaste    explicit ReferenceCountedBase()
564254721Semaste        : shared_owners_(-1)
565254721Semaste    {
566254721Semaste    }
567254721Semaste
568254721Semaste    void
569254721Semaste    add_shared();
570254721Semaste
571254721Semaste    void
572254721Semaste    release_shared();
573254721Semaste
574254721Semaste    long
575254721Semaste    use_count() const
576254721Semaste    {
577254721Semaste        return shared_owners_ + 1;
578254721Semaste    }
579254721Semaste
580254721Semasteprotected:
581254721Semaste    long shared_owners_;
582254721Semaste
583254721Semaste    friend class IntrusiveSharingPtr<T>;
584254721Semaste
585254721Semasteprivate:
586254721Semaste    ReferenceCountedBase(const ReferenceCountedBase&);
587254721Semaste    ReferenceCountedBase& operator=(const ReferenceCountedBase&);
588254721Semaste};
589254721Semaste
590254721Semaste    template <class T>
591254721Semaste    void
592254721Semaste    lldb_private::ReferenceCountedBase<T>::add_shared()
593254721Semaste    {
594263363Semaste#ifdef _MSC_VER
595263363Semaste        _InterlockedIncrement(&shared_owners_);
596263363Semaste#else
597263363Semaste        ++shared_owners_;
598263363Semaste#endif
599254721Semaste    }
600254721Semaste
601254721Semaste    template <class T>
602254721Semaste    void
603254721Semaste    lldb_private::ReferenceCountedBase<T>::release_shared()
604254721Semaste    {
605263363Semaste#ifdef _MSC_VER
606263363Semaste        if (_InterlockedDecrement(&shared_owners_) == -1)
607263363Semaste#else
608263363Semaste        if (--shared_owners_ == -1)
609263363Semaste#endif
610254721Semaste            delete static_cast<T*>(this);
611254721Semaste    }
612254721Semaste
613254721Semaste
614254721Semastetemplate <class T>
615254721Semasteclass ReferenceCountedBaseVirtual : public imp::shared_count
616254721Semaste{
617254721Semastepublic:
618254721Semaste    explicit ReferenceCountedBaseVirtual () :
619254721Semaste        imp::shared_count(-1)
620254721Semaste    {
621254721Semaste    }
622254721Semaste
623254721Semaste    virtual
624254721Semaste    ~ReferenceCountedBaseVirtual ()
625254721Semaste    {
626254721Semaste    }
627254721Semaste
628254721Semaste    virtual void on_zero_shared ();
629254721Semaste
630254721Semaste};
631254721Semaste
632254721Semastetemplate <class T>
633254721Semastevoid
634254721SemasteReferenceCountedBaseVirtual<T>::on_zero_shared()
635254721Semaste{
636254721Semaste}
637254721Semaste
638254721Semastetemplate <typename T>
639254721Semasteclass IntrusiveSharingPtr
640254721Semaste{
641254721Semastepublic:
642254721Semaste    typedef T element_type;
643254721Semaste
644254721Semaste    explicit
645254721Semaste    IntrusiveSharingPtr () :
646254721Semaste        ptr_(0)
647254721Semaste    {
648254721Semaste    }
649254721Semaste
650254721Semaste    explicit
651254721Semaste    IntrusiveSharingPtr (T* ptr) :
652254721Semaste        ptr_(ptr)
653254721Semaste    {
654254721Semaste        add_shared();
655254721Semaste    }
656254721Semaste
657254721Semaste    IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) :
658254721Semaste        ptr_(rhs.ptr_)
659254721Semaste    {
660254721Semaste        add_shared();
661254721Semaste    }
662254721Semaste
663254721Semaste    template <class X>
664254721Semaste    IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs)
665254721Semaste        : ptr_(rhs.get())
666254721Semaste    {
667254721Semaste        add_shared();
668254721Semaste    }
669254721Semaste
670254721Semaste    IntrusiveSharingPtr&
671254721Semaste    operator= (const IntrusiveSharingPtr& rhs)
672254721Semaste    {
673254721Semaste        reset(rhs.get());
674254721Semaste        return *this;
675254721Semaste    }
676254721Semaste
677254721Semaste    template <class X> IntrusiveSharingPtr&
678254721Semaste    operator= (const IntrusiveSharingPtr<X>& rhs)
679254721Semaste    {
680254721Semaste        reset(rhs.get());
681254721Semaste        return *this;
682254721Semaste    }
683254721Semaste
684254721Semaste    IntrusiveSharingPtr&
685254721Semaste    operator= (T *ptr)
686254721Semaste    {
687254721Semaste        reset(ptr);
688254721Semaste        return *this;
689254721Semaste    }
690254721Semaste
691254721Semaste    ~IntrusiveSharingPtr()
692254721Semaste    {
693254721Semaste        release_shared();
694254721Semaste#if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
695254721Semaste        // NULL out the pointer in objects which can help with leaks detection.
696254721Semaste        // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or
697254721Semaste        // when none of the LLDB_CONFIGURATION_XXX macros are defined since
698254721Semaste        // those would be builds for release. But for debug and release builds
699254721Semaste        // that are for development, we NULL out the pointers to catch potential
700254721Semaste        // issues.
701254721Semaste        ptr_ = NULL;
702254721Semaste#endif  // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
703254721Semaste    }
704254721Semaste
705254721Semaste    T&
706254721Semaste    operator*() const
707254721Semaste    {
708254721Semaste        return *ptr_;
709254721Semaste    }
710254721Semaste
711254721Semaste    T*
712254721Semaste    operator->() const
713254721Semaste    {
714254721Semaste        return ptr_;
715254721Semaste    }
716254721Semaste
717254721Semaste    T*
718254721Semaste    get() const
719254721Semaste    {
720254721Semaste        return ptr_;
721254721Semaste    }
722254721Semaste
723263363Semaste    explicit operator bool() const
724254721Semaste    {
725254721Semaste        return ptr_ != 0;
726254721Semaste    }
727254721Semaste
728254721Semaste    void
729254721Semaste    swap (IntrusiveSharingPtr& rhs)
730254721Semaste    {
731254721Semaste        std::swap(ptr_, rhs.ptr_);
732254721Semaste#if defined (ENABLE_SP_LOGGING)
733254721Semaste        track_sp (this, ptr_, use_count());
734254721Semaste        track_sp (&rhs, rhs.ptr_, rhs.use_count());
735254721Semaste#endif
736254721Semaste    }
737254721Semaste
738254721Semaste    void
739254721Semaste    reset(T* ptr = NULL)
740254721Semaste    {
741254721Semaste        IntrusiveSharingPtr(ptr).swap(*this);
742254721Semaste    }
743254721Semaste
744254721Semaste    long
745254721Semaste    use_count () const
746254721Semaste    {
747254721Semaste        if (ptr_)
748254721Semaste            return ptr_->use_count();
749254721Semaste        return 0;
750254721Semaste    }
751254721Semaste
752254721Semaste    bool
753254721Semaste    unique () const
754254721Semaste    {
755254721Semaste        return use_count () == 1;
756254721Semaste    }
757254721Semaste
758254721Semasteprivate:
759254721Semaste    element_type *ptr_;
760254721Semaste
761254721Semaste    void
762254721Semaste    add_shared()
763254721Semaste    {
764254721Semaste        if (ptr_)
765254721Semaste        {
766254721Semaste            ptr_->add_shared();
767254721Semaste#if defined (ENABLE_SP_LOGGING)
768254721Semaste            track_sp (this, ptr_, ptr_->use_count());
769254721Semaste#endif
770254721Semaste        }
771254721Semaste    }
772254721Semaste    void
773254721Semaste    release_shared()
774254721Semaste    {
775254721Semaste        if (ptr_)
776254721Semaste        {
777254721Semaste#if defined (ENABLE_SP_LOGGING)
778254721Semaste            track_sp (this, NULL, ptr_->use_count() - 1);
779254721Semaste#endif
780254721Semaste            ptr_->release_shared();
781254721Semaste        }
782254721Semaste    }
783254721Semaste};
784254721Semaste
785254721Semastetemplate<class T, class U>
786254721Semasteinline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
787254721Semaste{
788254721Semaste    return lhs.get() == rhs.get();
789254721Semaste}
790254721Semaste
791254721Semastetemplate<class T, class U>
792254721Semasteinline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs)
793254721Semaste{
794254721Semaste    return lhs.get() != rhs.get();
795254721Semaste}
796254721Semaste
797254721Semastetemplate<class T, class U>
798254721Semasteinline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs)
799254721Semaste{
800254721Semaste    return lhs.get() == rhs;
801254721Semaste}
802254721Semaste
803254721Semastetemplate<class T, class U>
804254721Semasteinline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs)
805254721Semaste{
806254721Semaste    return lhs.get() != rhs;
807254721Semaste}
808254721Semaste
809254721Semastetemplate<class T, class U>
810254721Semasteinline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs)
811254721Semaste{
812254721Semaste    return lhs == rhs.get();
813254721Semaste}
814254721Semaste
815254721Semastetemplate<class T, class U>
816254721Semasteinline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
817254721Semaste{
818254721Semaste    return lhs != rhs.get();
819254721Semaste}
820254721Semaste
821254721Semaste} // namespace lldb_private
822254721Semaste
823254721Semaste#endif  // utility_SharingPtr_h_
824