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 14cb7ce9a3SAxel Dörfler FileDescriptorCloser - closes a file descriptor 152851dbadSAxel Dörfler */ 162851dbadSAxel Dörfler 17d91215d3SAxel Dörfler 18ce8cfdb8SIngo Weinhold #include <stdlib.h> 19d91215d3SAxel Dörfler #include <unistd.h> 20d91215d3SAxel Dörfler 21ce8cfdb8SIngo Weinhold 22ce8cfdb8SIngo Weinhold namespace BPrivate { 23ce8cfdb8SIngo Weinhold 24d91215d3SAxel Dörfler 25ce8cfdb8SIngo Weinhold // AutoDeleter 26ce8cfdb8SIngo Weinhold 27f277fb63SIngo Weinhold template<typename C, typename DeleteFunc> 28ce8cfdb8SIngo Weinhold class AutoDeleter { 29ce8cfdb8SIngo Weinhold public: 30ce8cfdb8SIngo Weinhold inline AutoDeleter() 31ce8cfdb8SIngo Weinhold : fObject(NULL) 32ce8cfdb8SIngo Weinhold { 33ce8cfdb8SIngo Weinhold } 34ce8cfdb8SIngo Weinhold 35ce8cfdb8SIngo Weinhold inline AutoDeleter(C *object) 36ce8cfdb8SIngo Weinhold : fObject(object) 37ce8cfdb8SIngo Weinhold { 38ce8cfdb8SIngo Weinhold } 39ce8cfdb8SIngo Weinhold 40ce8cfdb8SIngo Weinhold inline ~AutoDeleter() 41ce8cfdb8SIngo Weinhold { 42ce8cfdb8SIngo Weinhold fDelete(fObject); 43ce8cfdb8SIngo Weinhold } 44ce8cfdb8SIngo Weinhold 45ce8cfdb8SIngo Weinhold inline void SetTo(C *object) 46ce8cfdb8SIngo Weinhold { 47f277fb63SIngo Weinhold if (object != fObject) { 48ce8cfdb8SIngo Weinhold fDelete(fObject); 49ce8cfdb8SIngo Weinhold fObject = object; 50ce8cfdb8SIngo Weinhold } 51f277fb63SIngo Weinhold } 52f277fb63SIngo Weinhold 53f277fb63SIngo Weinhold inline void Unset() 54f277fb63SIngo Weinhold { 55f277fb63SIngo Weinhold SetTo(NULL); 56f277fb63SIngo Weinhold } 57f277fb63SIngo Weinhold 58f277fb63SIngo Weinhold inline void Delete() 59f277fb63SIngo Weinhold { 60f277fb63SIngo Weinhold SetTo(NULL); 61f277fb63SIngo Weinhold } 62ce8cfdb8SIngo Weinhold 635519ed57SIngo Weinhold inline C *Get() const 645519ed57SIngo Weinhold { 655519ed57SIngo Weinhold return fObject; 665519ed57SIngo Weinhold } 675519ed57SIngo Weinhold 68ce8cfdb8SIngo Weinhold inline C *Detach() 69ce8cfdb8SIngo Weinhold { 70ce8cfdb8SIngo Weinhold C *object = fObject; 71ce8cfdb8SIngo Weinhold fObject = NULL; 72ce8cfdb8SIngo Weinhold return object; 73ce8cfdb8SIngo Weinhold } 74ce8cfdb8SIngo Weinhold 75b97e1292SOliver Tappe inline C *operator->() const 76b97e1292SOliver Tappe { 77b97e1292SOliver Tappe return fObject; 78b97e1292SOliver Tappe } 79b97e1292SOliver Tappe 8034cbfd39SIngo Weinhold protected: 81ce8cfdb8SIngo Weinhold C *fObject; 82f277fb63SIngo Weinhold DeleteFunc fDelete; 83ce8cfdb8SIngo Weinhold }; 84ce8cfdb8SIngo Weinhold 85ce8cfdb8SIngo Weinhold 86ce8cfdb8SIngo Weinhold // ObjectDeleter 87ce8cfdb8SIngo Weinhold 88ce8cfdb8SIngo Weinhold template<typename C> 89ce8cfdb8SIngo Weinhold struct ObjectDelete 90ce8cfdb8SIngo Weinhold { 91ce8cfdb8SIngo Weinhold inline void operator()(C *object) 92ce8cfdb8SIngo Weinhold { 93ce8cfdb8SIngo Weinhold delete object; 94ce8cfdb8SIngo Weinhold } 95ce8cfdb8SIngo Weinhold }; 96ce8cfdb8SIngo Weinhold 97ce8cfdb8SIngo Weinhold template<typename C> 98ce8cfdb8SIngo Weinhold struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> > 99ce8cfdb8SIngo Weinhold { 100ce8cfdb8SIngo Weinhold ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {} 101ce8cfdb8SIngo Weinhold ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {} 102ce8cfdb8SIngo Weinhold }; 103ce8cfdb8SIngo Weinhold 104ce8cfdb8SIngo Weinhold 105ce8cfdb8SIngo Weinhold // ArrayDeleter 106ce8cfdb8SIngo Weinhold 107ce8cfdb8SIngo Weinhold template<typename C> 108ce8cfdb8SIngo Weinhold struct ArrayDelete 109ce8cfdb8SIngo Weinhold { 110ce8cfdb8SIngo Weinhold inline void operator()(C *array) 111ce8cfdb8SIngo Weinhold { 112ce8cfdb8SIngo Weinhold delete[] array; 113ce8cfdb8SIngo Weinhold } 114ce8cfdb8SIngo Weinhold }; 115ce8cfdb8SIngo Weinhold 116ce8cfdb8SIngo Weinhold template<typename C> 117ce8cfdb8SIngo Weinhold struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> > 118ce8cfdb8SIngo Weinhold { 119ce8cfdb8SIngo Weinhold ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {} 120ce8cfdb8SIngo Weinhold ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {} 121ce8cfdb8SIngo Weinhold }; 122ce8cfdb8SIngo Weinhold 123ce8cfdb8SIngo Weinhold 124ce8cfdb8SIngo Weinhold // MemoryDeleter 125ce8cfdb8SIngo Weinhold 126ce8cfdb8SIngo Weinhold struct MemoryDelete 127ce8cfdb8SIngo Weinhold { 128ce8cfdb8SIngo Weinhold inline void operator()(void *memory) 129ce8cfdb8SIngo Weinhold { 130ce8cfdb8SIngo Weinhold free(memory); 131ce8cfdb8SIngo Weinhold } 132ce8cfdb8SIngo Weinhold }; 133ce8cfdb8SIngo Weinhold 134ce8cfdb8SIngo Weinhold struct MemoryDeleter : AutoDeleter<void, MemoryDelete > 135ce8cfdb8SIngo Weinhold { 136ce8cfdb8SIngo Weinhold MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {} 137ce8cfdb8SIngo Weinhold MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {} 138ce8cfdb8SIngo Weinhold }; 139ce8cfdb8SIngo Weinhold 14034cbfd39SIngo Weinhold 14134cbfd39SIngo Weinhold // CObjectDeleter 14234cbfd39SIngo Weinhold 14334cbfd39SIngo Weinhold template<typename Type, typename DestructorReturnType> 14434cbfd39SIngo Weinhold struct CObjectDelete 14534cbfd39SIngo Weinhold { 14634cbfd39SIngo Weinhold inline void operator()(Type *object) 14734cbfd39SIngo Weinhold { 148fe00c1a5SIngo Weinhold if (fDestructor != NULL && object != NULL) 14934cbfd39SIngo Weinhold fDestructor(object); 15034cbfd39SIngo Weinhold } 15134cbfd39SIngo Weinhold 15234cbfd39SIngo Weinhold template<typename Destructor> 15334cbfd39SIngo Weinhold inline void operator=(Destructor destructor) 15434cbfd39SIngo Weinhold { 155e378ab1cSIngo Weinhold fDestructor = destructor; 15634cbfd39SIngo Weinhold } 15734cbfd39SIngo Weinhold 15834cbfd39SIngo Weinhold private: 15934cbfd39SIngo Weinhold DestructorReturnType (*fDestructor)(Type*); 16034cbfd39SIngo Weinhold }; 16134cbfd39SIngo Weinhold 16234cbfd39SIngo Weinhold template<typename Type, typename DestructorReturnType = void> 16334cbfd39SIngo Weinhold struct CObjectDeleter 16434cbfd39SIngo Weinhold : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > 16534cbfd39SIngo Weinhold { 16634cbfd39SIngo Weinhold typedef AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > Base; 16734cbfd39SIngo Weinhold 16834cbfd39SIngo Weinhold template<typename Destructor> 16934cbfd39SIngo Weinhold CObjectDeleter(Destructor destructor) : Base() 17034cbfd39SIngo Weinhold { 17134cbfd39SIngo Weinhold Base::fDelete = destructor; 17234cbfd39SIngo Weinhold } 17334cbfd39SIngo Weinhold 17434cbfd39SIngo Weinhold template<typename Destructor> 17534cbfd39SIngo Weinhold CObjectDeleter(Type *object, Destructor destructor) : Base(object) 17634cbfd39SIngo Weinhold { 17734cbfd39SIngo Weinhold Base::fDelete = destructor; 17834cbfd39SIngo Weinhold } 17934cbfd39SIngo Weinhold }; 18034cbfd39SIngo Weinhold 181e378ab1cSIngo Weinhold 182e378ab1cSIngo Weinhold // MethodDeleter 183e378ab1cSIngo Weinhold 184e378ab1cSIngo Weinhold template<typename Type, typename DestructorReturnType> 185e378ab1cSIngo Weinhold struct MethodDelete 186e378ab1cSIngo Weinhold { 187e378ab1cSIngo Weinhold inline void operator()(Type *object) 188e378ab1cSIngo Weinhold { 189fe00c1a5SIngo Weinhold if (fDestructor && object != NULL) 190e378ab1cSIngo Weinhold (object->*fDestructor)(); 191e378ab1cSIngo Weinhold } 192e378ab1cSIngo Weinhold 193e378ab1cSIngo Weinhold template<typename Destructor> 194e378ab1cSIngo Weinhold inline void operator=(Destructor destructor) 195e378ab1cSIngo Weinhold { 196e378ab1cSIngo Weinhold fDestructor = destructor; 197e378ab1cSIngo Weinhold } 198e378ab1cSIngo Weinhold 199e378ab1cSIngo Weinhold private: 200e378ab1cSIngo Weinhold DestructorReturnType (Type::*fDestructor)(); 201e378ab1cSIngo Weinhold }; 202e378ab1cSIngo Weinhold 203e378ab1cSIngo Weinhold 204e378ab1cSIngo Weinhold template<typename Type, typename DestructorReturnType = void> 205e378ab1cSIngo Weinhold struct MethodDeleter 206e378ab1cSIngo Weinhold : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > 207e378ab1cSIngo Weinhold { 208e378ab1cSIngo Weinhold typedef AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > Base; 209e378ab1cSIngo Weinhold 210e378ab1cSIngo Weinhold template<typename Destructor> 211e378ab1cSIngo Weinhold MethodDeleter(Destructor destructor) : Base() 212e378ab1cSIngo Weinhold { 213e378ab1cSIngo Weinhold Base::fDelete = destructor; 214e378ab1cSIngo Weinhold } 215e378ab1cSIngo Weinhold 216e378ab1cSIngo Weinhold template<typename Destructor> 217e378ab1cSIngo Weinhold MethodDeleter(Type *object, Destructor destructor) : Base(object) 218e378ab1cSIngo Weinhold { 219e378ab1cSIngo Weinhold Base::fDelete = destructor; 220e378ab1cSIngo Weinhold } 221e378ab1cSIngo Weinhold }; 222e378ab1cSIngo Weinhold 223d91215d3SAxel Dörfler 224cb7ce9a3SAxel Dörfler // FileDescriptorCloser 225d91215d3SAxel Dörfler 226cb7ce9a3SAxel Dörfler struct FileDescriptorCloser { 2275b486787SIngo Weinhold inline FileDescriptorCloser() 2285b486787SIngo Weinhold : 2295b486787SIngo Weinhold fDescriptor(-1) 2305b486787SIngo Weinhold { 2315b486787SIngo Weinhold } 2325b486787SIngo Weinhold 233cb7ce9a3SAxel Dörfler inline FileDescriptorCloser(int descriptor) 234d91215d3SAxel Dörfler : 235d91215d3SAxel Dörfler fDescriptor(descriptor) 236d91215d3SAxel Dörfler { 237d91215d3SAxel Dörfler } 238d91215d3SAxel Dörfler 239cb7ce9a3SAxel Dörfler inline ~FileDescriptorCloser() 240d91215d3SAxel Dörfler { 2415b486787SIngo Weinhold SetTo(-1); 242d91215d3SAxel Dörfler } 243d91215d3SAxel Dörfler 2445b486787SIngo Weinhold inline void SetTo(int descriptor) 245d91215d3SAxel Dörfler { 2465b486787SIngo Weinhold if (fDescriptor >= 0) 2475b486787SIngo Weinhold close(fDescriptor); 2485b486787SIngo Weinhold 2495b486787SIngo Weinhold fDescriptor = descriptor; 2505b486787SIngo Weinhold } 2515b486787SIngo Weinhold 2525b486787SIngo Weinhold inline void Unset() 2535b486787SIngo Weinhold { 2545b486787SIngo Weinhold SetTo(-1); 2555b486787SIngo Weinhold } 2565b486787SIngo Weinhold 2575b486787SIngo Weinhold inline int Detach() 2585b486787SIngo Weinhold { 2595b486787SIngo Weinhold int descriptor = fDescriptor; 260d91215d3SAxel Dörfler fDescriptor = -1; 2615b486787SIngo Weinhold return descriptor; 262d91215d3SAxel Dörfler } 263d91215d3SAxel Dörfler 264d91215d3SAxel Dörfler private: 265d91215d3SAxel Dörfler int fDescriptor; 266d91215d3SAxel Dörfler }; 267d91215d3SAxel Dörfler 268d91215d3SAxel Dörfler 269ce8cfdb8SIngo Weinhold } // namespace BPrivate 270ce8cfdb8SIngo Weinhold 271d91215d3SAxel Dörfler 272*18f5cd17SIngo Weinhold using ::BPrivate::ObjectDeleter; 273*18f5cd17SIngo Weinhold using ::BPrivate::ArrayDeleter; 274*18f5cd17SIngo Weinhold using ::BPrivate::MemoryDeleter; 275*18f5cd17SIngo Weinhold using ::BPrivate::CObjectDeleter; 276*18f5cd17SIngo Weinhold using ::BPrivate::MethodDeleter; 277*18f5cd17SIngo Weinhold using ::BPrivate::FileDescriptorCloser; 278d91215d3SAxel Dörfler 279ce8cfdb8SIngo Weinhold 280ce8cfdb8SIngo Weinhold #endif // _AUTO_DELETER_H 281