1 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. 2 // Copyright (c) 2001, 2002 Peter Dimov 3 // 4 // Permission to copy, use, modify, sell and distribute this software 5 // is granted provided this copyright notice appears in all copies. 6 // This software is provided "as is" without express or implied 7 // warranty, and with no claim as to its suitability for any purpose. 8 // 9 // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. 10 // 11 12 // scoped_ptr mimics a built-in pointer except that it guarantees deletion 13 // of the object pointed to, either on destruction of the scoped_ptr or via 14 // an explicit reset(). scoped_ptr is a simple solution for simple needs; 15 // use shared_ptr or std::auto_ptr if your needs are more complex. 16 17 // scoped_ptr_malloc added in by Google. When one of 18 // these goes out of scope, instead of doing a delete or delete[], it 19 // calls free(). scoped_ptr_malloc<char> is likely to see much more 20 // use than any other specializations. 21 22 // release() added in by Google. Use this to conditionally 23 // transfer ownership of a heap-allocated object to the caller, usually on 24 // method success. 25 #ifndef TALK_BASE_SCOPED_PTR_H__ 26 #define TALK_BASE_SCOPED_PTR_H__ 27 28 #include <cstddef> // for std::ptrdiff_t 29 #include <stdlib.h> // for free() decl 30 31 #include "talk/base/common.h" // for ASSERT 32 33 #ifdef _WIN32 34 namespace std { using ::ptrdiff_t; }; 35 #endif // _WIN32 36 37 namespace talk_base { 38 39 template <typename T> 40 class scoped_ptr { 41 private: 42 43 T* ptr; 44 45 scoped_ptr(scoped_ptr const &); 46 scoped_ptr & operator=(scoped_ptr const &); 47 48 public: 49 50 typedef T element_type; 51 52 explicit scoped_ptr(T* p = NULL): ptr(p) {} 53 54 ~scoped_ptr() { 55 typedef char type_must_be_complete[sizeof(T)]; 56 delete ptr; 57 } 58 59 void reset(T* p = NULL) { 60 typedef char type_must_be_complete[sizeof(T)]; 61 62 if (ptr != p) { 63 T* obj = ptr; 64 ptr = p; 65 // Delete last, in case obj destructor indirectly results in ~scoped_ptr 66 delete obj; 67 } 68 } 69 70 T& operator*() const { 71 ASSERT(ptr != NULL); 72 return *ptr; 73 } 74 75 T* operator->() const { 76 ASSERT(ptr != NULL); 77 return ptr; 78 } 79 80 T* get() const { 81 return ptr; 82 } 83 84 void swap(scoped_ptr & b) { 85 T* tmp = b.ptr; 86 b.ptr = ptr; 87 ptr = tmp; 88 } 89 90 T* release() { 91 T* tmp = ptr; 92 ptr = NULL; 93 return tmp; 94 } 95 96 T** accept() { 97 if (ptr) { 98 delete ptr; 99 ptr = NULL; 100 } 101 return &ptr; 102 } 103 104 T** use() { 105 return &ptr; 106 } 107 }; 108 109 template<typename T> inline 110 void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) { 111 a.swap(b); 112 } 113 114 115 116 117 // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to 118 // is guaranteed, either on destruction of the scoped_array or via an explicit 119 // reset(). Use shared_array or std::vector if your needs are more complex. 120 121 template<typename T> 122 class scoped_array { 123 private: 124 125 T* ptr; 126 127 scoped_array(scoped_array const &); 128 scoped_array & operator=(scoped_array const &); 129 130 public: 131 132 typedef T element_type; 133 134 explicit scoped_array(T* p = NULL) : ptr(p) {} 135 136 ~scoped_array() { 137 typedef char type_must_be_complete[sizeof(T)]; 138 delete[] ptr; 139 } 140 141 void reset(T* p = NULL) { 142 typedef char type_must_be_complete[sizeof(T)]; 143 144 if (ptr != p) { 145 T* arr = ptr; 146 ptr = p; 147 // Delete last, in case arr destructor indirectly results in ~scoped_array 148 delete [] arr; 149 } 150 } 151 152 T& operator[](std::ptrdiff_t i) const { 153 ASSERT(ptr != NULL); 154 ASSERT(i >= 0); 155 return ptr[i]; 156 } 157 158 T* get() const { 159 return ptr; 160 } 161 162 void swap(scoped_array & b) { 163 T* tmp = b.ptr; 164 b.ptr = ptr; 165 ptr = tmp; 166 } 167 168 T* release() { 169 T* tmp = ptr; 170 ptr = NULL; 171 return tmp; 172 } 173 174 T** accept() { 175 if (ptr) { 176 delete [] ptr; 177 ptr = NULL; 178 } 179 return &ptr; 180 } 181 }; 182 183 template<class T> inline 184 void swap(scoped_array<T>& a, scoped_array<T>& b) { 185 a.swap(b); 186 } 187 188 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a 189 // second template argument, the function used to free the object. 190 191 template<typename T, void (*FF)(void*) = free> class scoped_ptr_malloc { 192 private: 193 194 T* ptr; 195 196 scoped_ptr_malloc(scoped_ptr_malloc const &); 197 scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); 198 199 public: 200 201 typedef T element_type; 202 203 explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} 204 205 ~scoped_ptr_malloc() { 206 FF(static_cast<void*>(ptr)); 207 } 208 209 void reset(T* p = 0) { 210 if (ptr != p) { 211 FF(static_cast<void*>(ptr)); 212 ptr = p; 213 } 214 } 215 216 T& operator*() const { 217 ASSERT(ptr != 0); 218 return *ptr; 219 } 220 221 T* operator->() const { 222 ASSERT(ptr != 0); 223 return ptr; 224 } 225 226 T* get() const { 227 return ptr; 228 } 229 230 void swap(scoped_ptr_malloc & b) { 231 T* tmp = b.ptr; 232 b.ptr = ptr; 233 ptr = tmp; 234 } 235 236 T* release() { 237 T* tmp = ptr; 238 ptr = 0; 239 return tmp; 240 } 241 242 T** accept() { 243 if (ptr) { 244 FF(static_cast<void*>(ptr)); 245 ptr = 0; 246 } 247 return &ptr; 248 } 249 }; 250 251 template<typename T, void (*FF)(void*)> inline 252 void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) { 253 a.swap(b); 254 } 255 256 } // namespace talk_base 257 258 #endif // #ifndef TALK_BASE_SCOPED_PTR_H__ 259