1 /* 2 * Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _AUTO_DELETER_H 6 #define _AUTO_DELETER_H 7 8 9 /*! Scope-based automatic deletion of objects/arrays. 10 ObjectDeleter - deletes an object 11 ArrayDeleter - deletes an array 12 MemoryDeleter - free()s malloc()ed memory 13 CObjectDeleter - calls an arbitrary specified destructor function 14 FileDescriptorCloser - closes a file descriptor 15 */ 16 17 18 #include <stdlib.h> 19 #include <unistd.h> 20 21 22 namespace BPrivate { 23 24 25 // AutoDeleter 26 27 template<typename C, typename DeleteFunc> 28 class AutoDeleter { 29 public: 30 inline AutoDeleter() 31 : fObject(NULL) 32 { 33 } 34 35 inline AutoDeleter(C *object) 36 : fObject(object) 37 { 38 } 39 40 inline ~AutoDeleter() 41 { 42 fDelete(fObject); 43 } 44 45 inline void SetTo(C *object) 46 { 47 if (object != fObject) { 48 fDelete(fObject); 49 fObject = object; 50 } 51 } 52 53 inline void Unset() 54 { 55 SetTo(NULL); 56 } 57 58 inline void Delete() 59 { 60 SetTo(NULL); 61 } 62 63 inline C *Get() const 64 { 65 return fObject; 66 } 67 68 inline C *Detach() 69 { 70 C *object = fObject; 71 fObject = NULL; 72 return object; 73 } 74 75 inline C *operator->() const 76 { 77 return fObject; 78 } 79 80 protected: 81 C *fObject; 82 DeleteFunc fDelete; 83 84 private: 85 AutoDeleter(const AutoDeleter&); 86 AutoDeleter& operator=(const AutoDeleter&); 87 }; 88 89 90 // ObjectDeleter 91 92 template<typename C> 93 struct ObjectDelete 94 { 95 inline void operator()(C *object) 96 { 97 delete object; 98 } 99 }; 100 101 template<typename C> 102 struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> > 103 { 104 ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {} 105 ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {} 106 }; 107 108 109 // ArrayDeleter 110 111 template<typename C> 112 struct ArrayDelete 113 { 114 inline void operator()(C *array) 115 { 116 delete[] array; 117 } 118 }; 119 120 template<typename C> 121 struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> > 122 { 123 ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {} 124 ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {} 125 126 inline C& operator[](size_t index) const 127 { 128 return this->Get()[index]; 129 } 130 }; 131 132 133 // MemoryDeleter 134 135 struct MemoryDelete 136 { 137 inline void operator()(void *memory) 138 { 139 free(memory); 140 } 141 }; 142 143 struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 144 { 145 MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} 146 MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 147 }; 148 149 150 // CObjectDeleter 151 152 template<typename Type, typename DestructorReturnType> 153 struct CObjectDelete 154 { 155 inline void operator()(Type *object) 156 { 157 if (fDestructor != NULL && object != NULL) 158 fDestructor(object); 159 } 160 161 template<typename Destructor> 162 inline void operator=(Destructor destructor) 163 { 164 fDestructor = destructor; 165 } 166 167 private: 168 DestructorReturnType (*fDestructor)(Type*); 169 }; 170 171 template<typename Type, typename DestructorReturnType = void> 172 struct CObjectDeleter 173 : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > 174 { 175 typedef AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > Base; 176 177 template<typename Destructor> 178 CObjectDeleter(Destructor destructor) : Base() 179 { 180 Base::fDelete = destructor; 181 } 182 183 template<typename Destructor> 184 CObjectDeleter(Type *object, Destructor destructor) : Base(object) 185 { 186 Base::fDelete = destructor; 187 } 188 }; 189 190 191 // MethodDeleter 192 193 template<typename Type, typename DestructorReturnType> 194 struct MethodDelete 195 { 196 inline void operator()(Type *object) 197 { 198 if (fDestructor && object != NULL) 199 (object->*fDestructor)(); 200 } 201 202 template<typename Destructor> 203 inline void operator=(Destructor destructor) 204 { 205 fDestructor = destructor; 206 } 207 208 private: 209 DestructorReturnType (Type::*fDestructor)(); 210 }; 211 212 213 template<typename Type, typename DestructorReturnType = void> 214 struct MethodDeleter 215 : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > 216 { 217 typedef AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > Base; 218 219 template<typename Destructor> 220 MethodDeleter(Destructor destructor) : Base() 221 { 222 Base::fDelete = destructor; 223 } 224 225 template<typename Destructor> 226 MethodDeleter(Type *object, Destructor destructor) : Base(object) 227 { 228 Base::fDelete = destructor; 229 } 230 }; 231 232 233 // FileDescriptorCloser 234 235 struct FileDescriptorCloser { 236 inline FileDescriptorCloser() 237 : 238 fDescriptor(-1) 239 { 240 } 241 242 inline FileDescriptorCloser(int descriptor) 243 : 244 fDescriptor(descriptor) 245 { 246 } 247 248 inline ~FileDescriptorCloser() 249 { 250 SetTo(-1); 251 } 252 253 inline void SetTo(int descriptor) 254 { 255 if (fDescriptor >= 0) 256 close(fDescriptor); 257 258 fDescriptor = descriptor; 259 } 260 261 inline void Unset() 262 { 263 SetTo(-1); 264 } 265 266 inline int Get() 267 { 268 return fDescriptor; 269 } 270 271 inline int Detach() 272 { 273 int descriptor = fDescriptor; 274 fDescriptor = -1; 275 return descriptor; 276 } 277 278 private: 279 int fDescriptor; 280 }; 281 282 283 } // namespace BPrivate 284 285 286 using ::BPrivate::ObjectDeleter; 287 using ::BPrivate::ArrayDeleter; 288 using ::BPrivate::MemoryDeleter; 289 using ::BPrivate::CObjectDeleter; 290 using ::BPrivate::MethodDeleter; 291 using ::BPrivate::FileDescriptorCloser; 292 293 294 #endif // _AUTO_DELETER_H 295