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