1 //===-- CFCReleaser.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 CoreFoundationCPP_CFReleaser_h_ 11 #define CoreFoundationCPP_CFReleaser_h_ 12 13 #include <CoreFoundation/CoreFoundation.h> 14 15 #ifdef __cplusplus 16 17 #include <assert.h> 18 19 //---------------------------------------------------------------------- 20 // Templatized CF helper class that can own any CF pointer and will 21 // call CFRelease() on any valid pointer it owns unless that pointer is 22 // explicitly released using the release() member function. This class 23 // is designed to mimic the std::auto_ptr<T> class and has all of the 24 // same functions. The one thing to watch out for is the 25 // CFCReleaser<T>::release() function won't actually CFRelease any owned 26 // pointer, it is designed to relinquish ownership of the pointer just 27 // like std:auto_ptr<T>::release() does. 28 //---------------------------------------------------------------------- 29 template <class T> 30 class CFCReleaser 31 { 32 public: 33 //---------------------------------------------------------- 34 // Constructor that takes a pointer to a CF object that is 35 // to be released when this object goes out of scope 36 //---------------------------------------------------------- 37 CFCReleaser(T ptr = NULL) : _ptr(ptr)38 _ptr(ptr) 39 { 40 } 41 42 //---------------------------------------------------------- 43 // Copy constructor 44 // 45 // Note that copying a CFCReleaser will not transfer 46 // ownership of the contained pointer, but it will bump its 47 // reference count. This is where this class differs from 48 // std::auto_ptr. 49 //---------------------------------------------------------- CFCReleaser(const CFCReleaser & rhs)50 CFCReleaser(const CFCReleaser& rhs) : 51 _ptr(rhs.get()) 52 { 53 if (get()) 54 ::CFRetain(get()); 55 } 56 57 58 //---------------------------------------------------------- 59 // The destructor will release the pointer that it contains 60 // if it has a valid pointer. 61 //---------------------------------------------------------- ~CFCReleaser()62 virtual ~CFCReleaser() 63 { 64 reset(); 65 } 66 67 //---------------------------------------------------------- 68 // Assignment operator. 69 // 70 // Note that assigning one CFCReleaser to another will 71 // not transfer ownership of the contained pointer, but it 72 // will bump its reference count. This is where this class 73 // differs from std::auto_ptr. 74 //---------------------------------------------------------- 75 CFCReleaser& 76 operator= (const CFCReleaser<T>& rhs) 77 { 78 if (this != &rhs) 79 { 80 // Replace our owned pointer with the new one 81 reset(rhs.get()); 82 // Retain the current pointer that we own 83 if (get()) 84 ::CFRetain(get()); 85 } 86 return *this; 87 } 88 89 //---------------------------------------------------------- 90 // Get the address of the contained type in case it needs 91 // to be passed to a function that will fill in a pointer 92 // value. The function currently will assert if _ptr is not 93 // NULL because the only time this method should be used is 94 // if another function will modify the contents, and we 95 // could leak a pointer if this is not NULL. If the 96 // assertion fires, check the offending code, or call 97 // reset() prior to using the "ptr_address()" member to make 98 // sure any owned objects has CFRelease called on it. 99 // I had to add the "enforce_null" bool here because some 100 // API's require the pointer address even though they don't change it. 101 //---------------------------------------------------------- 102 T* 103 ptr_address(bool enforce_null = true) 104 { 105 if (enforce_null) 106 assert (_ptr == NULL); 107 return &_ptr; 108 } 109 110 //---------------------------------------------------------- 111 // Access the pointer itself 112 //---------------------------------------------------------- 113 T get()114 get() 115 { 116 return _ptr; 117 } 118 119 const T get()120 get() const 121 { 122 return _ptr; 123 } 124 125 126 //---------------------------------------------------------- 127 // Set a new value for the pointer and CFRelease our old 128 // value if we had a valid one. 129 //---------------------------------------------------------- 130 void 131 reset(T ptr = NULL) 132 { 133 if ((_ptr != NULL) && (ptr != _ptr)) 134 ::CFRelease(_ptr); 135 _ptr = ptr; 136 } 137 138 //---------------------------------------------------------- 139 // Release ownership without calling CFRelease. This class 140 // is designed to mimic std::auto_ptr<T>, so the release 141 // method releases ownership of the contained pointer 142 // and does NOT call CFRelease. 143 //---------------------------------------------------------- 144 T release()145 release() 146 { 147 T tmp = _ptr; 148 _ptr = NULL; 149 return tmp; 150 } 151 152 private: 153 T _ptr; 154 }; 155 156 #endif // #ifdef __cplusplus 157 #endif // #ifndef CoreFoundationCPP_CFReleaser_h_ 158 159