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