xref: /haiku/headers/private/shared/AutoDeleter.h (revision 18f5cd171bc62a0bf90c48f3a07a8f6e2f8b2297)
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