12851dbadSAxel Dörfler /* 22851dbadSAxel Dörfler * Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved. 32851dbadSAxel Dörfler * Distributed under the terms of the MIT License. 42851dbadSAxel Dörfler */ 5ce8cfdb8SIngo Weinhold #ifndef _AUTO_DELETER_H 6ce8cfdb8SIngo Weinhold #define _AUTO_DELETER_H 7ce8cfdb8SIngo Weinhold 8d91215d3SAxel Dörfler 92851dbadSAxel Dörfler /*! Scope-based automatic deletion of objects/arrays. 102851dbadSAxel Dörfler ObjectDeleter - deletes an object 112851dbadSAxel Dörfler ArrayDeleter - deletes an array 122851dbadSAxel Dörfler MemoryDeleter - free()s malloc()ed memory 1334cbfd39SIngo Weinhold CObjectDeleter - calls an arbitrary specified destructor function 14058b29acSX512 MethodObjectDeleter - calls an arbitrary object function in given struct ptr 1584b1893bSX512 HandleDeleter - use arbitrary handle type and destructor function 1684b1893bSX512 FileDescriptorCloser - closes a file descriptor, based on HandleDeleter 172851dbadSAxel Dörfler */ 182851dbadSAxel Dörfler 19d91215d3SAxel Dörfler 20ce8cfdb8SIngo Weinhold #include <stdlib.h> 21d91215d3SAxel Dörfler #include <unistd.h> 22d1ca0fccSX512 #include <SupportDefs.h> 23d91215d3SAxel Dörfler 24*97dc7e3bSAugustin Cavalier #ifndef _OS_H 25*97dc7e3bSAugustin Cavalier extern "C" { 26*97dc7e3bSAugustin Cavalier extern void debugger(const char *message); 27*97dc7e3bSAugustin Cavalier } 28*97dc7e3bSAugustin Cavalier #endif 29*97dc7e3bSAugustin Cavalier 30ce8cfdb8SIngo Weinhold 31ce8cfdb8SIngo Weinhold namespace BPrivate { 32ce8cfdb8SIngo Weinhold 33d91215d3SAxel Dörfler 34ce8cfdb8SIngo Weinhold // AutoDeleter 35ce8cfdb8SIngo Weinhold 36f277fb63SIngo Weinhold template<typename C, typename DeleteFunc> 37ce8cfdb8SIngo Weinhold class AutoDeleter { 38ce8cfdb8SIngo Weinhold public: AutoDeleter()39ce8cfdb8SIngo Weinhold inline AutoDeleter() 40ce8cfdb8SIngo Weinhold : fObject(NULL) 41ce8cfdb8SIngo Weinhold { 42ce8cfdb8SIngo Weinhold } 43ce8cfdb8SIngo Weinhold AutoDeleter(C * object)44ce8cfdb8SIngo Weinhold inline AutoDeleter(C *object) 45ce8cfdb8SIngo Weinhold : fObject(object) 46ce8cfdb8SIngo Weinhold { 47ce8cfdb8SIngo Weinhold } 48ce8cfdb8SIngo Weinhold ~AutoDeleter()49ce8cfdb8SIngo Weinhold inline ~AutoDeleter() 50ce8cfdb8SIngo Weinhold { 5176ab8567SX512 DeleteFunc destructor; 5276ab8567SX512 destructor(fObject); 53ce8cfdb8SIngo Weinhold } 54ce8cfdb8SIngo Weinhold SetTo(C * object)55ce8cfdb8SIngo Weinhold inline void SetTo(C *object) 56ce8cfdb8SIngo Weinhold { 57*97dc7e3bSAugustin Cavalier if (object == fObject && object != NULL) 58*97dc7e3bSAugustin Cavalier debugger("identical objects"); 59*97dc7e3bSAugustin Cavalier 60f277fb63SIngo Weinhold if (object != fObject) { 6176ab8567SX512 DeleteFunc destructor; 6276ab8567SX512 destructor(fObject); 63ce8cfdb8SIngo Weinhold fObject = object; 64ce8cfdb8SIngo Weinhold } 65f277fb63SIngo Weinhold } 66f277fb63SIngo Weinhold Unset()67f277fb63SIngo Weinhold inline void Unset() 68f277fb63SIngo Weinhold { 69f277fb63SIngo Weinhold SetTo(NULL); 70f277fb63SIngo Weinhold } 71f277fb63SIngo Weinhold Delete()72f277fb63SIngo Weinhold inline void Delete() 73f277fb63SIngo Weinhold { 74f277fb63SIngo Weinhold SetTo(NULL); 75f277fb63SIngo Weinhold } 76ce8cfdb8SIngo Weinhold IsSet()77d1ca0fccSX512 inline bool IsSet() const 78d1ca0fccSX512 { 79d1ca0fccSX512 return fObject != NULL; 80d1ca0fccSX512 } 81d1ca0fccSX512 Get()825519ed57SIngo Weinhold inline C *Get() const 835519ed57SIngo Weinhold { 845519ed57SIngo Weinhold return fObject; 855519ed57SIngo Weinhold } 865519ed57SIngo Weinhold Detach()87ce8cfdb8SIngo Weinhold inline C *Detach() 88ce8cfdb8SIngo Weinhold { 89ce8cfdb8SIngo Weinhold C *object = fObject; 90ce8cfdb8SIngo Weinhold fObject = NULL; 91ce8cfdb8SIngo Weinhold return object; 92ce8cfdb8SIngo Weinhold } 93ce8cfdb8SIngo Weinhold 94b97e1292SOliver Tappe inline C *operator->() const 95b97e1292SOliver Tappe { 96b97e1292SOliver Tappe return fObject; 97b97e1292SOliver Tappe } 98b97e1292SOliver Tappe 9934cbfd39SIngo Weinhold protected: 100ce8cfdb8SIngo Weinhold C *fObject; 101ec43e4f4SX512 102ec43e4f4SX512 private: 103ec43e4f4SX512 AutoDeleter(const AutoDeleter&); 104ec43e4f4SX512 AutoDeleter& operator=(const AutoDeleter&); 105ce8cfdb8SIngo Weinhold }; 106ce8cfdb8SIngo Weinhold 107ce8cfdb8SIngo Weinhold 108ce8cfdb8SIngo Weinhold // ObjectDeleter 109ce8cfdb8SIngo Weinhold 110ce8cfdb8SIngo Weinhold template<typename C> 111ce8cfdb8SIngo Weinhold struct ObjectDelete 112ce8cfdb8SIngo Weinhold { operatorObjectDelete113ce8cfdb8SIngo Weinhold inline void operator()(C *object) 114ce8cfdb8SIngo Weinhold { 115ce8cfdb8SIngo Weinhold delete object; 116ce8cfdb8SIngo Weinhold } 117ce8cfdb8SIngo Weinhold }; 118ce8cfdb8SIngo Weinhold 119ce8cfdb8SIngo Weinhold template<typename C> 120ce8cfdb8SIngo Weinhold struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> > 121ce8cfdb8SIngo Weinhold { ObjectDeleterObjectDeleter122ce8cfdb8SIngo Weinhold ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {} ObjectDeleterObjectDeleter123ce8cfdb8SIngo Weinhold ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {} 124ce8cfdb8SIngo Weinhold }; 125ce8cfdb8SIngo Weinhold 126ce8cfdb8SIngo Weinhold 127ce8cfdb8SIngo Weinhold // ArrayDeleter 128ce8cfdb8SIngo Weinhold 129ce8cfdb8SIngo Weinhold template<typename C> 130ce8cfdb8SIngo Weinhold struct ArrayDelete 131ce8cfdb8SIngo Weinhold { operatorArrayDelete132ce8cfdb8SIngo Weinhold inline void operator()(C *array) 133ce8cfdb8SIngo Weinhold { 134ce8cfdb8SIngo Weinhold delete[] array; 135ce8cfdb8SIngo Weinhold } 136ce8cfdb8SIngo Weinhold }; 137ce8cfdb8SIngo Weinhold 138ce8cfdb8SIngo Weinhold template<typename C> 139ce8cfdb8SIngo Weinhold struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> > 140ce8cfdb8SIngo Weinhold { ArrayDeleterArrayDeleter141ce8cfdb8SIngo Weinhold ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {} ArrayDeleterArrayDeleter142ce8cfdb8SIngo Weinhold ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {} 1438301c498SX512 1448301c498SX512 inline C& operator[](size_t index) const 1458301c498SX512 { 1468301c498SX512 return this->Get()[index]; 1478301c498SX512 } 148ce8cfdb8SIngo Weinhold }; 149ce8cfdb8SIngo Weinhold 150ce8cfdb8SIngo Weinhold 151ce8cfdb8SIngo Weinhold // MemoryDeleter 152ce8cfdb8SIngo Weinhold 153ce8cfdb8SIngo Weinhold struct MemoryDelete 154ce8cfdb8SIngo Weinhold { operatorMemoryDelete155ce8cfdb8SIngo Weinhold inline void operator()(void *memory) 156ce8cfdb8SIngo Weinhold { 157ce8cfdb8SIngo Weinhold free(memory); 158ce8cfdb8SIngo Weinhold } 159ce8cfdb8SIngo Weinhold }; 160ce8cfdb8SIngo Weinhold 161ce8cfdb8SIngo Weinhold struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 162ce8cfdb8SIngo Weinhold { MemoryDeleterMemoryDeleter163ce8cfdb8SIngo Weinhold MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} MemoryDeleterMemoryDeleter164ce8cfdb8SIngo Weinhold MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 165ce8cfdb8SIngo Weinhold }; 166ce8cfdb8SIngo Weinhold 16734cbfd39SIngo Weinhold 16834cbfd39SIngo Weinhold // CObjectDeleter 16934cbfd39SIngo Weinhold 1707d775e79SX512 template<typename Type, typename DestructorReturnType, 1717d775e79SX512 DestructorReturnType (*Destructor)(Type*)> 17234cbfd39SIngo Weinhold struct CObjectDelete 17334cbfd39SIngo Weinhold { operatorCObjectDelete17434cbfd39SIngo Weinhold inline void operator()(Type *object) 17534cbfd39SIngo Weinhold { 1767d775e79SX512 if (object != NULL) 1777d775e79SX512 Destructor(object); 17834cbfd39SIngo Weinhold } 17934cbfd39SIngo Weinhold }; 18034cbfd39SIngo Weinhold 1817d775e79SX512 template<typename Type, typename DestructorReturnType, 1827d775e79SX512 DestructorReturnType (*Destructor)(Type*)> 18334cbfd39SIngo Weinhold struct CObjectDeleter 1847d775e79SX512 : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> > 18534cbfd39SIngo Weinhold { 1867d775e79SX512 typedef AutoDeleter<Type, 1877d775e79SX512 CObjectDelete<Type, DestructorReturnType, Destructor> > Base; 18834cbfd39SIngo Weinhold CObjectDeleterCObjectDeleter1897d775e79SX512 CObjectDeleter() : Base() 19034cbfd39SIngo Weinhold { 19134cbfd39SIngo Weinhold } 19234cbfd39SIngo Weinhold CObjectDeleterCObjectDeleter1937d775e79SX512 CObjectDeleter(Type *object) : Base(object) 19434cbfd39SIngo Weinhold { 19534cbfd39SIngo Weinhold } 19634cbfd39SIngo Weinhold }; 19734cbfd39SIngo Weinhold 198e378ab1cSIngo Weinhold 199e378ab1cSIngo Weinhold // MethodDeleter 200e378ab1cSIngo Weinhold 201aecba913SX512 template<typename Type, typename DestructorReturnType, 202aecba913SX512 DestructorReturnType (Type::*Destructor)()> 203e378ab1cSIngo Weinhold struct MethodDelete 204e378ab1cSIngo Weinhold { operatorMethodDelete205e378ab1cSIngo Weinhold inline void operator()(Type *object) 206e378ab1cSIngo Weinhold { 207aecba913SX512 if (object != NULL) 208aecba913SX512 (object->*Destructor)(); 209e378ab1cSIngo Weinhold } 210e378ab1cSIngo Weinhold }; 211e378ab1cSIngo Weinhold 212e378ab1cSIngo Weinhold 213aecba913SX512 template<typename Type, typename DestructorReturnType, 214aecba913SX512 DestructorReturnType (Type::*Destructor)()> 215e378ab1cSIngo Weinhold struct MethodDeleter 216aecba913SX512 : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> > 217e378ab1cSIngo Weinhold { 218aecba913SX512 typedef AutoDeleter<Type, 219aecba913SX512 MethodDelete<Type, DestructorReturnType, Destructor> > Base; 220e378ab1cSIngo Weinhold MethodDeleterMethodDeleter221aecba913SX512 MethodDeleter() : Base() 222e378ab1cSIngo Weinhold { 223e378ab1cSIngo Weinhold } 224e378ab1cSIngo Weinhold MethodDeleterMethodDeleter225aecba913SX512 MethodDeleter(Type *object) : Base(object) 226e378ab1cSIngo Weinhold { 227e378ab1cSIngo Weinhold } 228e378ab1cSIngo Weinhold }; 229e378ab1cSIngo Weinhold 230d91215d3SAxel Dörfler 231058b29acSX512 // MethodObjectDeleter 232058b29acSX512 233058b29acSX512 template<typename Type, typename Table, Table **table, 234058b29acSX512 void (*Table::*Deleter)(Type*)> 235058b29acSX512 struct MethodObjectDelete { operatorMethodObjectDelete236058b29acSX512 inline void operator()(Type *object) 237058b29acSX512 { 238058b29acSX512 if (object != NULL) 239058b29acSX512 ((**table).*Deleter)(object); 240058b29acSX512 } 241058b29acSX512 }; 242058b29acSX512 243058b29acSX512 template<typename Type, typename Table, Table **table, 244058b29acSX512 typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)> 245058b29acSX512 struct MethodObjectDeleter 246058b29acSX512 : AutoDeleter<Type, MethodObjectDelete<Type, Table, table, Deleter> > 247058b29acSX512 { 248058b29acSX512 typedef AutoDeleter<Type, 249058b29acSX512 MethodObjectDelete<Type, Table, table, Deleter> > Base; 250058b29acSX512 MethodObjectDeleterMethodObjectDeleter251058b29acSX512 MethodObjectDeleter() : Base() {} MethodObjectDeleterMethodObjectDeleter252058b29acSX512 MethodObjectDeleter(Type *object) : Base(object) {} 253058b29acSX512 }; 254058b29acSX512 255058b29acSX512 25684b1893bSX512 // HandleDeleter 257d91215d3SAxel Dörfler 258d1ca0fccSX512 struct StatusHandleChecker 259d1ca0fccSX512 { operatorStatusHandleChecker260d1ca0fccSX512 inline bool operator()(status_t handle) 261d1ca0fccSX512 { 262d1ca0fccSX512 return handle >= B_OK; 263d1ca0fccSX512 } 264d1ca0fccSX512 }; 265d1ca0fccSX512 26684b1893bSX512 template<typename C, typename DestructorResult, 267d1ca0fccSX512 DestructorResult (*Destructor)(C), C nullValue = -1, 268d1ca0fccSX512 typename Checker = StatusHandleChecker> 26984b1893bSX512 class HandleDeleter { 27084b1893bSX512 public: HandleDeleter()27184b1893bSX512 inline HandleDeleter() 27284b1893bSX512 : fHandle(nullValue) 2735b486787SIngo Weinhold { 2745b486787SIngo Weinhold } 2755b486787SIngo Weinhold HandleDeleter(C handle)27684b1893bSX512 inline HandleDeleter(C handle) 27784b1893bSX512 : fHandle(handle) 278d91215d3SAxel Dörfler { 279d91215d3SAxel Dörfler } 280d91215d3SAxel Dörfler ~HandleDeleter()28184b1893bSX512 inline ~HandleDeleter() 282d91215d3SAxel Dörfler { 283d1ca0fccSX512 if (IsSet()) 28484b1893bSX512 Destructor(fHandle); 285d91215d3SAxel Dörfler } 286d91215d3SAxel Dörfler SetTo(C handle)28784b1893bSX512 inline void SetTo(C handle) 288d91215d3SAxel Dörfler { 28984b1893bSX512 if (handle != fHandle) { 290d1ca0fccSX512 if (IsSet()) 29184b1893bSX512 Destructor(fHandle); 29284b1893bSX512 fHandle = handle; 29384b1893bSX512 } 2945b486787SIngo Weinhold } 2955b486787SIngo Weinhold Unset()2965b486787SIngo Weinhold inline void Unset() 2975b486787SIngo Weinhold { 29884b1893bSX512 SetTo(nullValue); 2995b486787SIngo Weinhold } 3005b486787SIngo Weinhold Delete()30184b1893bSX512 inline void Delete() 302b29db8ebSX512 { 30384b1893bSX512 SetTo(nullValue); 304b29db8ebSX512 } 305b29db8ebSX512 IsSet()306d1ca0fccSX512 inline bool IsSet() const 307d1ca0fccSX512 { 308d1ca0fccSX512 Checker isHandleSet; 309d1ca0fccSX512 return isHandleSet(fHandle); 310d1ca0fccSX512 } 311d1ca0fccSX512 Get()31284b1893bSX512 inline C Get() const 3135b486787SIngo Weinhold { 31484b1893bSX512 return fHandle; 315d91215d3SAxel Dörfler } 316d91215d3SAxel Dörfler Detach()31784b1893bSX512 inline C Detach() 31884b1893bSX512 { 31984b1893bSX512 C handle = fHandle; 32084b1893bSX512 fHandle = nullValue; 32184b1893bSX512 return handle; 32284b1893bSX512 } 32384b1893bSX512 32484b1893bSX512 protected: 32584b1893bSX512 C fHandle; 32684b1893bSX512 327d91215d3SAxel Dörfler private: 32884b1893bSX512 HandleDeleter(const HandleDeleter&); 32984b1893bSX512 HandleDeleter& operator=(const HandleDeleter&); 330d91215d3SAxel Dörfler }; 331d91215d3SAxel Dörfler 332d91215d3SAxel Dörfler 33384b1893bSX512 // FileDescriptorCloser 33484b1893bSX512 33584b1893bSX512 typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser; 33684b1893bSX512 33784b1893bSX512 338ce8cfdb8SIngo Weinhold } // namespace BPrivate 339ce8cfdb8SIngo Weinhold 340d91215d3SAxel Dörfler 34118f5cd17SIngo Weinhold using ::BPrivate::ObjectDeleter; 34218f5cd17SIngo Weinhold using ::BPrivate::ArrayDeleter; 34318f5cd17SIngo Weinhold using ::BPrivate::MemoryDeleter; 34418f5cd17SIngo Weinhold using ::BPrivate::CObjectDeleter; 34518f5cd17SIngo Weinhold using ::BPrivate::MethodDeleter; 346058b29acSX512 using ::BPrivate::MethodObjectDeleter; 34784b1893bSX512 using ::BPrivate::HandleDeleter; 34818f5cd17SIngo Weinhold using ::BPrivate::FileDescriptorCloser; 349d91215d3SAxel Dörfler 350ce8cfdb8SIngo Weinhold 351ce8cfdb8SIngo Weinhold #endif // _AUTO_DELETER_H 352