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 85 86 // ObjectDeleter 87 88 template<typename C> 89 struct ObjectDelete 90 { 91 inline void operator()(C *object) 92 { 93 delete object; 94 } 95 }; 96 97 template<typename C> 98 struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> > 99 { 100 ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {} 101 ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {} 102 }; 103 104 105 // ArrayDeleter 106 107 template<typename C> 108 struct ArrayDelete 109 { 110 inline void operator()(C *array) 111 { 112 delete[] array; 113 } 114 }; 115 116 template<typename C> 117 struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> > 118 { 119 ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {} 120 ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {} 121 }; 122 123 124 // MemoryDeleter 125 126 struct MemoryDelete 127 { 128 inline void operator()(void *memory) 129 { 130 free(memory); 131 } 132 }; 133 134 struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 135 { 136 MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} 137 MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 138 }; 139 140 141 // CObjectDeleter 142 143 template<typename Type, typename DestructorReturnType> 144 struct CObjectDelete 145 { 146 inline void operator()(Type *object) 147 { 148 if (fDestructor != NULL && object != NULL) 149 fDestructor(object); 150 } 151 152 template<typename Destructor> 153 inline void operator=(Destructor destructor) 154 { 155 fDestructor = destructor; 156 } 157 158 private: 159 DestructorReturnType (*fDestructor)(Type*); 160 }; 161 162 template<typename Type, typename DestructorReturnType = void> 163 struct CObjectDeleter 164 : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > 165 { 166 typedef AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > Base; 167 168 template<typename Destructor> 169 CObjectDeleter(Destructor destructor) : Base() 170 { 171 Base::fDelete = destructor; 172 } 173 174 template<typename Destructor> 175 CObjectDeleter(Type *object, Destructor destructor) : Base(object) 176 { 177 Base::fDelete = destructor; 178 } 179 }; 180 181 182 // MethodDeleter 183 184 template<typename Type, typename DestructorReturnType> 185 struct MethodDelete 186 { 187 inline void operator()(Type *object) 188 { 189 if (fDestructor && object != NULL) 190 (object->*fDestructor)(); 191 } 192 193 template<typename Destructor> 194 inline void operator=(Destructor destructor) 195 { 196 fDestructor = destructor; 197 } 198 199 private: 200 DestructorReturnType (Type::*fDestructor)(); 201 }; 202 203 204 template<typename Type, typename DestructorReturnType = void> 205 struct MethodDeleter 206 : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > 207 { 208 typedef AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > Base; 209 210 template<typename Destructor> 211 MethodDeleter(Destructor destructor) : Base() 212 { 213 Base::fDelete = destructor; 214 } 215 216 template<typename Destructor> 217 MethodDeleter(Type *object, Destructor destructor) : Base(object) 218 { 219 Base::fDelete = destructor; 220 } 221 }; 222 223 224 // FileDescriptorCloser 225 226 struct FileDescriptorCloser { 227 inline FileDescriptorCloser() 228 : 229 fDescriptor(-1) 230 { 231 } 232 233 inline FileDescriptorCloser(int descriptor) 234 : 235 fDescriptor(descriptor) 236 { 237 } 238 239 inline ~FileDescriptorCloser() 240 { 241 SetTo(-1); 242 } 243 244 inline void SetTo(int descriptor) 245 { 246 if (fDescriptor >= 0) 247 close(fDescriptor); 248 249 fDescriptor = descriptor; 250 } 251 252 inline void Unset() 253 { 254 SetTo(-1); 255 } 256 257 inline int Detach() 258 { 259 int descriptor = fDescriptor; 260 fDescriptor = -1; 261 return descriptor; 262 } 263 264 private: 265 int fDescriptor; 266 }; 267 268 269 } // namespace BPrivate 270 271 272 using BPrivate::ObjectDeleter; 273 using BPrivate::ArrayDeleter; 274 using BPrivate::MemoryDeleter; 275 using BPrivate::CObjectDeleter; 276 using BPrivate::MethodDeleter; 277 using BPrivate::FileDescriptorCloser; 278 279 280 #endif // _AUTO_DELETER_H 281