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 MethodObjectDeleter - calls an arbitrary object function in given struct ptr 15 HandleDeleter - use arbitrary handle type and destructor function 16 FileDescriptorCloser - closes a file descriptor, based on HandleDeleter 17 */ 18 19 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <SupportDefs.h> 23 24 #ifndef _OS_H 25 extern "C" { 26 extern void debugger(const char *message); 27 } 28 #endif 29 30 31 namespace BPrivate { 32 33 34 // AutoDeleter 35 36 template<typename C, typename DeleteFunc> 37 class AutoDeleter { 38 public: 39 inline AutoDeleter() 40 : fObject(NULL) 41 { 42 } 43 44 inline AutoDeleter(C *object) 45 : fObject(object) 46 { 47 } 48 49 inline ~AutoDeleter() 50 { 51 DeleteFunc destructor; 52 destructor(fObject); 53 } 54 55 inline void SetTo(C *object) 56 { 57 if (object == fObject && object != NULL) 58 debugger("identical objects"); 59 60 if (object != fObject) { 61 DeleteFunc destructor; 62 destructor(fObject); 63 fObject = object; 64 } 65 } 66 67 inline void Unset() 68 { 69 SetTo(NULL); 70 } 71 72 inline void Delete() 73 { 74 SetTo(NULL); 75 } 76 77 inline bool IsSet() const 78 { 79 return fObject != NULL; 80 } 81 82 inline C *Get() const 83 { 84 return fObject; 85 } 86 87 inline C *Detach() 88 { 89 C *object = fObject; 90 fObject = NULL; 91 return object; 92 } 93 94 inline C *operator->() const 95 { 96 return fObject; 97 } 98 99 protected: 100 C *fObject; 101 102 private: 103 AutoDeleter(const AutoDeleter&); 104 AutoDeleter& operator=(const AutoDeleter&); 105 }; 106 107 108 // ObjectDeleter 109 110 template<typename C> 111 struct ObjectDelete 112 { 113 inline void operator()(C *object) 114 { 115 delete object; 116 } 117 }; 118 119 template<typename C> 120 struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> > 121 { 122 ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {} 123 ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {} 124 }; 125 126 127 // ArrayDeleter 128 129 template<typename C> 130 struct ArrayDelete 131 { 132 inline void operator()(C *array) 133 { 134 delete[] array; 135 } 136 }; 137 138 template<typename C> 139 struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> > 140 { 141 ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {} 142 ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {} 143 144 inline C& operator[](size_t index) const 145 { 146 return this->Get()[index]; 147 } 148 }; 149 150 151 // MemoryDeleter 152 153 struct MemoryDelete 154 { 155 inline void operator()(void *memory) 156 { 157 free(memory); 158 } 159 }; 160 161 struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 162 { 163 MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} 164 MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 165 }; 166 167 168 // CObjectDeleter 169 170 template<typename Type, typename DestructorReturnType, 171 DestructorReturnType (*Destructor)(Type*)> 172 struct CObjectDelete 173 { 174 inline void operator()(Type *object) 175 { 176 if (object != NULL) 177 Destructor(object); 178 } 179 }; 180 181 template<typename Type, typename DestructorReturnType, 182 DestructorReturnType (*Destructor)(Type*)> 183 struct CObjectDeleter 184 : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> > 185 { 186 typedef AutoDeleter<Type, 187 CObjectDelete<Type, DestructorReturnType, Destructor> > Base; 188 189 CObjectDeleter() : Base() 190 { 191 } 192 193 CObjectDeleter(Type *object) : Base(object) 194 { 195 } 196 }; 197 198 199 // MethodDeleter 200 201 template<typename Type, typename DestructorReturnType, 202 DestructorReturnType (Type::*Destructor)()> 203 struct MethodDelete 204 { 205 inline void operator()(Type *object) 206 { 207 if (object != NULL) 208 (object->*Destructor)(); 209 } 210 }; 211 212 213 template<typename Type, typename DestructorReturnType, 214 DestructorReturnType (Type::*Destructor)()> 215 struct MethodDeleter 216 : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> > 217 { 218 typedef AutoDeleter<Type, 219 MethodDelete<Type, DestructorReturnType, Destructor> > Base; 220 221 MethodDeleter() : Base() 222 { 223 } 224 225 MethodDeleter(Type *object) : Base(object) 226 { 227 } 228 }; 229 230 231 // MethodObjectDeleter 232 233 template<typename Type, typename Table, Table **table, 234 void (*Table::*Deleter)(Type*)> 235 struct MethodObjectDelete { 236 inline void operator()(Type *object) 237 { 238 if (object != NULL) 239 ((**table).*Deleter)(object); 240 } 241 }; 242 243 template<typename Type, typename Table, Table **table, 244 typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)> 245 struct MethodObjectDeleter 246 : AutoDeleter<Type, MethodObjectDelete<Type, Table, table, Deleter> > 247 { 248 typedef AutoDeleter<Type, 249 MethodObjectDelete<Type, Table, table, Deleter> > Base; 250 251 MethodObjectDeleter() : Base() {} 252 MethodObjectDeleter(Type *object) : Base(object) {} 253 }; 254 255 256 // HandleDeleter 257 258 struct StatusHandleChecker 259 { 260 inline bool operator()(status_t handle) 261 { 262 return handle >= B_OK; 263 } 264 }; 265 266 template<typename C, typename DestructorResult, 267 DestructorResult (*Destructor)(C), C nullValue = -1, 268 typename Checker = StatusHandleChecker> 269 class HandleDeleter { 270 public: 271 inline HandleDeleter() 272 : fHandle(nullValue) 273 { 274 } 275 276 inline HandleDeleter(C handle) 277 : fHandle(handle) 278 { 279 } 280 281 inline ~HandleDeleter() 282 { 283 if (IsSet()) 284 Destructor(fHandle); 285 } 286 287 inline void SetTo(C handle) 288 { 289 if (handle != fHandle) { 290 if (IsSet()) 291 Destructor(fHandle); 292 fHandle = handle; 293 } 294 } 295 296 inline void Unset() 297 { 298 SetTo(nullValue); 299 } 300 301 inline void Delete() 302 { 303 SetTo(nullValue); 304 } 305 306 inline bool IsSet() const 307 { 308 Checker isHandleSet; 309 return isHandleSet(fHandle); 310 } 311 312 inline C Get() const 313 { 314 return fHandle; 315 } 316 317 inline C Detach() 318 { 319 C handle = fHandle; 320 fHandle = nullValue; 321 return handle; 322 } 323 324 protected: 325 C fHandle; 326 327 private: 328 HandleDeleter(const HandleDeleter&); 329 HandleDeleter& operator=(const HandleDeleter&); 330 }; 331 332 333 // FileDescriptorCloser 334 335 typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser; 336 337 338 } // namespace BPrivate 339 340 341 using ::BPrivate::ObjectDeleter; 342 using ::BPrivate::ArrayDeleter; 343 using ::BPrivate::MemoryDeleter; 344 using ::BPrivate::CObjectDeleter; 345 using ::BPrivate::MethodDeleter; 346 using ::BPrivate::MethodObjectDeleter; 347 using ::BPrivate::HandleDeleter; 348 using ::BPrivate::FileDescriptorCloser; 349 350 351 #endif // _AUTO_DELETER_H 352