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 25extern "C" { 26extern void debugger(const char *message); 27} 28#endif 29 30 31namespace BPrivate { 32 33 34// AutoDeleter 35 36template<typename C, typename DeleteFunc> 37class AutoDeleter { 38public: 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 99protected: 100 C *fObject; 101 102private: 103 AutoDeleter(const AutoDeleter&); 104 AutoDeleter& operator=(const AutoDeleter&); 105}; 106 107 108// ObjectDeleter 109 110template<typename C> 111struct ObjectDelete 112{ 113 inline void operator()(C *object) 114 { 115 delete object; 116 } 117}; 118 119template<typename C> 120struct 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 129template<typename C> 130struct ArrayDelete 131{ 132 inline void operator()(C *array) 133 { 134 delete[] array; 135 } 136}; 137 138template<typename C> 139struct 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 153struct MemoryDelete 154{ 155 inline void operator()(void *memory) 156 { 157 free(memory); 158 } 159}; 160 161struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 162{ 163 MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} 164 MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 165}; 166 167 168// CObjectDeleter 169 170template<typename Type, typename DestructorReturnType, 171 DestructorReturnType (*Destructor)(Type*)> 172struct CObjectDelete 173{ 174 inline void operator()(Type *object) 175 { 176 if (object != NULL) 177 Destructor(object); 178 } 179}; 180 181template<typename Type, typename DestructorReturnType, 182 DestructorReturnType (*Destructor)(Type*)> 183struct 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 201template<typename Type, typename DestructorReturnType, 202 DestructorReturnType (Type::*Destructor)()> 203struct MethodDelete 204{ 205 inline void operator()(Type *object) 206 { 207 if (object != NULL) 208 (object->*Destructor)(); 209 } 210}; 211 212 213template<typename Type, typename DestructorReturnType, 214 DestructorReturnType (Type::*Destructor)()> 215struct 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 233template<typename Type, typename Table, Table **table, 234 void (*Table::*Deleter)(Type*)> 235struct MethodObjectDelete { 236 inline void operator()(Type *object) 237 { 238 if (object != NULL) 239 ((**table).*Deleter)(object); 240 } 241}; 242 243template<typename Type, typename Table, Table **table, 244 typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)> 245struct 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 258struct StatusHandleChecker 259{ 260 inline bool operator()(status_t handle) 261 { 262 return handle >= B_OK; 263 } 264}; 265 266template<typename C, typename DestructorResult, 267 DestructorResult (*Destructor)(C), C nullValue = -1, 268 typename Checker = StatusHandleChecker> 269class HandleDeleter { 270public: 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 324protected: 325 C fHandle; 326 327private: 328 HandleDeleter(const HandleDeleter&); 329 HandleDeleter& operator=(const HandleDeleter&); 330}; 331 332 333// FileDescriptorCloser 334 335typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser; 336 337 338} // namespace BPrivate 339 340 341using ::BPrivate::ObjectDeleter; 342using ::BPrivate::ArrayDeleter; 343using ::BPrivate::MemoryDeleter; 344using ::BPrivate::CObjectDeleter; 345using ::BPrivate::MethodDeleter; 346using ::BPrivate::MethodObjectDeleter; 347using ::BPrivate::HandleDeleter; 348using ::BPrivate::FileDescriptorCloser; 349 350 351#endif // _AUTO_DELETER_H 352