1a2769a33c94f021a609a462b28ebea069eba6f74Misha Brukman//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
2567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
3567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//                     The LLVM Compiler Infrastructure
4567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
5567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// This file is distributed under the University of Illinois Open Source
6567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// License. See LICENSE.TXT for details.
7567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
8567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
9567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
10567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// This file defines IntrusiveRefCntPtr, a template class that
11567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// implements a "smart" pointer for objects that maintain their own
12567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two
13567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// generic base classes for objects that wish to have their lifetimes
14567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// managed using reference counting.
15567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
16567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
17567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// LLVM-style casting.
18567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//
19567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
20567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
21674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
22674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
23567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
24567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov#include "llvm/Support/Casting.h"
25e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer#include "llvm/Support/Compiler.h"
2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <atomic>
275acc40a0373ed183d944b4f165dbb0b6798d5a92Benjamin Kramer#include <memory>
28567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
29567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikovnamespace llvm {
30567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
31567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template <class T>
3295e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov  class IntrusiveRefCntPtr;
33567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
34567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
35567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov/// RefCountedBase - A generic base class for objects that wish to
36567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  have their lifetimes managed using reference counts. Classes
37567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  subclass RefCountedBase to obtain such functionality, and are
3846588d4fb9c38ed7ce0cb561884fc20230dc9fd7Axel Naumann///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
39567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  which automatically handle the management of reference counts.
40567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  Objects that subclass RefCountedBase should not be allocated on
41567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  the stack, as invoking "delete" (which is called when the
42567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  reference count hits 0) on such objects is an error.
43567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
44567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template <class Derived>
45567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  class RefCountedBase {
4610fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    mutable unsigned ref_cnt;
47567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
48116e2348edee6c216a9e37484b62fc2fda595208Ted Kremenek  public:
49567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    RefCountedBase() : ref_cnt(0) {}
50f24944953986ad1e0a78279e6c3288e15a7e2619Ted Kremenek    RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
51567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
5210fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    void Retain() const { ++ref_cnt; }
5310fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    void Release() const {
54567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      assert (ref_cnt > 0 && "Reference count is already zero.");
5510fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne      if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
56567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
57567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  };
58567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
59567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
60567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov/// RefCountedBaseVPTR - A class that has the same function as
61567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  RefCountedBase, but with a virtual destructor. Should be used
6295e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  instead of RefCountedBase for classes that already have virtual
6395e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  methods to enforce dynamic allocation via 'new'. Classes that
6495e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  inherit from RefCountedBaseVPTR can't be allocated on stack -
6595e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  attempting to do this will produce a compile error.
66567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
67567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  class RefCountedBaseVPTR {
6810fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    mutable unsigned ref_cnt;
692d24e2a396a1d211baaeedf32148a3b657240170David Blaikie    virtual void anchor();
70567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
71567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  protected:
72567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    RefCountedBaseVPTR() : ref_cnt(0) {}
73f24944953986ad1e0a78279e6c3288e15a7e2619Ted Kremenek    RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
74f24944953986ad1e0a78279e6c3288e15a7e2619Ted Kremenek
75567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    virtual ~RefCountedBaseVPTR() {}
76567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
7710fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    void Retain() const { ++ref_cnt; }
7810fdd5a0f622bdea4003ffa818eeb9486bfb0730Peter Collingbourne    void Release() const {
79567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      assert (ref_cnt > 0 && "Reference count is already zero.");
80567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      if (--ref_cnt == 0) delete this;
81567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
82567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
83b518c25b3e3ec03da389ca48910ded42ca1305e3Argyrios Kyrtzidis    template <typename T>
8441aa108f743ed3b97cdf060ae25cfef38af5bc9eManuel Klimek    friend struct IntrusiveRefCntPtrInfo;
85567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  };
86567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
870004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek
880004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek  template <typename T> struct IntrusiveRefCntPtrInfo {
890004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek    static void retain(T *obj) { obj->Retain(); }
900004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek    static void release(T *obj) { obj->Release(); }
910004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek  };
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief A thread-safe version of \c llvm::RefCountedBase.
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// A generic base class for objects that wish to have their lifetimes managed
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// obtain such functionality, and are typically handled with
9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// management of reference counts.
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <class Derived>
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesclass ThreadSafeRefCountedBase {
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  mutable std::atomic<int> RefCount;
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesprotected:
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ThreadSafeRefCountedBase() : RefCount(0) {}
10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic:
10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void Retain() const { ++RefCount; }
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void Release() const {
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    int NewRefCount = --RefCount;
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(NewRefCount >= 0 && "Reference count was already zero.");
11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (NewRefCount == 0)
11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      delete static_cast<const Derived*>(this);
11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
1170004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek
118567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
119567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
120567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  that assumes the wrapped object has a reference count associated
121567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  with it that can be managed via calls to
122567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
123567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  manage reference counts via the RAII idiom: upon creation of
124567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  smart pointer the reference count of the wrapped object is
125567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  incremented and upon destruction of the smart pointer the
126567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  reference count is decremented.  This class also safely handles
127567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov///  wrapping NULL pointers.
12895e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///
12995e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov/// Reference counting is implemented via calls to
13095e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  Obj->Retain()/Obj->Release(). Release() is required to destroy
13195e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  the object when the reference count reaches zero. Inheriting from
13295e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  RefCountedBase/RefCountedBaseVPTR takes care of this
13395e78348f08fab152b2b03c516cc9f22ed60b8deAnton Korobeynikov///  automatically.
134567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
135567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template <typename T>
136567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  class IntrusiveRefCntPtr {
137567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    T* Obj;
13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
139567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  public:
140567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    typedef T element_type;
141567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
143567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
14497cf71a5179bc4167a750deb09836ae4a75389cbTed Kremenek    IntrusiveRefCntPtr(T* obj) : Obj(obj) {
145567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      retain();
146567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
147567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
148567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
149567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      retain();
150567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
151567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
152e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer    IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      S.Obj = nullptr;
154e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer    }
155e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer
156e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer    template <class X>
157cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
158e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer      S.Obj = 0;
159e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer    }
160e3f75f8797b9752bfe7923bff9a87a15a6fe3552Benjamin Kramer
161567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    template <class X>
162567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      : Obj(S.get()) {
164567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      retain();
165567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
166567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
16791a8ad71aa5d08e37a8a4ed364d0dae720d8ea7cBenjamin Kramer    IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
16891a8ad71aa5d08e37a8a4ed364d0dae720d8ea7cBenjamin Kramer      swap(S);
169567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      return *this;
170567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
171567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
172567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    ~IntrusiveRefCntPtr() { release(); }
173567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
174567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    T& operator*() const { return *Obj; }
175567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
176567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    T* operator->() const { return Obj; }
177567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
178cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    T* get() const { return Obj; }
179567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
180cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    LLVM_EXPLICIT operator bool() const { return Obj; }
181567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
182567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    void swap(IntrusiveRefCntPtr& other) {
183567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      T* tmp = other.Obj;
184567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      other.Obj = Obj;
185567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov      Obj = tmp;
186567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
187a81ac8f2b5d4f61f7bc353f95cc1d0a05266f51cMichael J. Spencer
188a81ac8f2b5d4f61f7bc353f95cc1d0a05266f51cMichael J. Spencer    void reset() {
189a81ac8f2b5d4f61f7bc353f95cc1d0a05266f51cMichael J. Spencer      release();
190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Obj = nullptr;
191a81ac8f2b5d4f61f7bc353f95cc1d0a05266f51cMichael J. Spencer    }
192a81ac8f2b5d4f61f7bc353f95cc1d0a05266f51cMichael J. Spencer
19347f0f1856f189e9e0d9540bd3f82b26f77088a7dTed Kremenek    void resetWithoutRelease() {
19447f0f1856f189e9e0d9540bd3f82b26f77088a7dTed Kremenek      Obj = 0;
19547f0f1856f189e9e0d9540bd3f82b26f77088a7dTed Kremenek    }
196567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
197567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  private:
1980004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek    void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
1990004d86704f5c116e43bb6f867d3eba7423640e5Ted Kremenek    void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
200567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  };
201567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
202567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
203567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
204567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         const IntrusiveRefCntPtr<U>& B)
205567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
206cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A.get() == B.get();
207567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
208567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
209567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
210567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
211567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         const IntrusiveRefCntPtr<U>& B)
212567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A.get() != B.get();
214567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
215567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
216567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
217567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
218567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         U* B)
219567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
220cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A.get() == B;
221567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
222567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
223567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
224567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
225567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         U* B)
226567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A.get() != B;
228567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
229567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
230567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
231567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator==(T* A,
232567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         const IntrusiveRefCntPtr<U>& B)
233567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
234cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A == B.get();
235567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
236567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
237567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T, class U>
238567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  inline bool operator!=(T* A,
239567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov                         const IntrusiveRefCntPtr<U>& B)
240567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  {
241cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return A != B.get();
242cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
243cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
244cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  template <class T>
245cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
246cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return !B;
247cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
248cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
249cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  template <class T>
250cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
251cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return B == A;
252cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
253cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
254cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  template <class T>
255cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
256cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return !(A == B);
257cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
258cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
259cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  template <class T>
260cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
261cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return !(A == B);
262567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  }
263567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
264567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
265567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov// LLVM-style downcasting support for IntrusiveRefCntPtr objects
266567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov//===----------------------------------------------------------------------===//
267567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
268567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
269567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    typedef T* SimpleType;
2707fe65d691dcce550d53ec9310913aab67ab6d654Rafael Espindola    static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
271cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return Val.get();
272567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
273567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  };
274567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
275567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
2767fe65d691dcce550d53ec9310913aab67ab6d654Rafael Espindola    typedef /*const*/ T* SimpleType;
277567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
278cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return Val.get();
279567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov    }
280567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov  };
281567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
282567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov} // end namespace llvm
283567a273370fd7f1f1e8dd4a372d7b81f26df7a47Anton Korobeynikov
284674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H
285