xref: /haiku/headers/private/shared/AutoDeleter.h (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 	HandleDeleter  - use arbitrary handle type and destructor function
15 	FileDescriptorCloser - closes a file descriptor, based on HandleDeleter
16 */
17 
18 
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <SupportDefs.h>
22 
23 
24 namespace BPrivate {
25 
26 
27 // AutoDeleter
28 
29 template<typename C, typename DeleteFunc>
30 class AutoDeleter {
31 public:
32 	inline AutoDeleter()
33 		: fObject(NULL)
34 	{
35 	}
36 
37 	inline AutoDeleter(C *object)
38 		: fObject(object)
39 	{
40 	}
41 
42 	inline ~AutoDeleter()
43 	{
44 		DeleteFunc destructor;
45 		destructor(fObject);
46 	}
47 
48 	inline void SetTo(C *object)
49 	{
50 		if (object != fObject) {
51 			DeleteFunc destructor;
52 			destructor(fObject);
53 			fObject = object;
54 		}
55 	}
56 
57 	inline void Unset()
58 	{
59 		SetTo(NULL);
60 	}
61 
62 	inline void Delete()
63 	{
64 		SetTo(NULL);
65 	}
66 
67 	inline bool IsSet() const
68 	{
69 		return fObject != NULL;
70 	}
71 
72 	inline C *Get() const
73 	{
74 		return fObject;
75 	}
76 
77 	inline C *Detach()
78 	{
79 		C *object = fObject;
80 		fObject = NULL;
81 		return object;
82 	}
83 
84 	inline C *operator->() const
85 	{
86 		return fObject;
87 	}
88 
89 protected:
90 	C			*fObject;
91 
92 private:
93 	AutoDeleter(const AutoDeleter&);
94 	AutoDeleter& operator=(const AutoDeleter&);
95 };
96 
97 
98 // ObjectDeleter
99 
100 template<typename C>
101 struct ObjectDelete
102 {
103 	inline void operator()(C *object)
104 	{
105 		delete object;
106 	}
107 };
108 
109 template<typename C>
110 struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
111 {
112 	ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
113 	ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
114 };
115 
116 
117 // ArrayDeleter
118 
119 template<typename C>
120 struct ArrayDelete
121 {
122 	inline void operator()(C *array)
123 	{
124 		delete[] array;
125 	}
126 };
127 
128 template<typename C>
129 struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
130 {
131 	ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
132 	ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}
133 
134 	inline C& operator[](size_t index) const
135 	{
136 		return this->Get()[index];
137 	}
138 };
139 
140 
141 // MemoryDeleter
142 
143 struct MemoryDelete
144 {
145 	inline void operator()(void *memory)
146 	{
147 		free(memory);
148 	}
149 };
150 
151 struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
152 {
153 	MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
154 	MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
155 };
156 
157 
158 // CObjectDeleter
159 
160 template<typename Type, typename DestructorReturnType,
161 	DestructorReturnType (*Destructor)(Type*)>
162 struct CObjectDelete
163 {
164 	inline void operator()(Type *object)
165 	{
166 		if (object != NULL)
167 			Destructor(object);
168 	}
169 };
170 
171 template<typename Type, typename DestructorReturnType,
172 	DestructorReturnType (*Destructor)(Type*)>
173 struct CObjectDeleter
174 	: AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> >
175 {
176 	typedef AutoDeleter<Type,
177 		CObjectDelete<Type, DestructorReturnType, Destructor> > Base;
178 
179 	CObjectDeleter() : Base()
180 	{
181 	}
182 
183 	CObjectDeleter(Type *object) : Base(object)
184 	{
185 	}
186 };
187 
188 
189 // MethodDeleter
190 
191 template<typename Type, typename DestructorReturnType,
192 	DestructorReturnType (Type::*Destructor)()>
193 struct MethodDelete
194 {
195 	inline void operator()(Type *object)
196 	{
197 		if (object != NULL)
198 			(object->*Destructor)();
199 	}
200 };
201 
202 
203 template<typename Type, typename DestructorReturnType,
204 	DestructorReturnType (Type::*Destructor)()>
205 struct MethodDeleter
206 	: AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> >
207 {
208 	typedef AutoDeleter<Type,
209 		MethodDelete<Type, DestructorReturnType, Destructor> > Base;
210 
211 	MethodDeleter() : Base()
212 	{
213 	}
214 
215 	MethodDeleter(Type *object) : Base(object)
216 	{
217 	}
218 };
219 
220 
221 // HandleDeleter
222 
223 struct StatusHandleChecker
224 {
225 	inline bool operator()(status_t handle)
226 	{
227 		return handle >= B_OK;
228 	}
229 };
230 
231 template<typename C, typename DestructorResult,
232 	DestructorResult (*Destructor)(C), C nullValue = -1,
233 	typename Checker = StatusHandleChecker>
234 class HandleDeleter {
235 public:
236 	inline HandleDeleter()
237 		: fHandle(nullValue)
238 	{
239 	}
240 
241 	inline HandleDeleter(C handle)
242 		: fHandle(handle)
243 	{
244 	}
245 
246 	inline ~HandleDeleter()
247 	{
248 		if (IsSet())
249 			Destructor(fHandle);
250 	}
251 
252 	inline void SetTo(C handle)
253 	{
254 		if (handle != fHandle) {
255 			if (IsSet())
256 				Destructor(fHandle);
257 			fHandle = handle;
258 		}
259 	}
260 
261 	inline void Unset()
262 	{
263 		SetTo(nullValue);
264 	}
265 
266 	inline void Delete()
267 	{
268 		SetTo(nullValue);
269 	}
270 
271 	inline bool IsSet() const
272 	{
273 		Checker isHandleSet;
274 		return isHandleSet(fHandle);
275 	}
276 
277 	inline C Get() const
278 	{
279 		return fHandle;
280 	}
281 
282 	inline C Detach()
283 	{
284 		C handle = fHandle;
285 		fHandle = nullValue;
286 		return handle;
287 	}
288 
289 protected:
290 	C			fHandle;
291 
292 private:
293 	HandleDeleter(const HandleDeleter&);
294 	HandleDeleter& operator=(const HandleDeleter&);
295 };
296 
297 
298 // FileDescriptorCloser
299 
300 typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser;
301 
302 
303 }	// namespace BPrivate
304 
305 
306 using ::BPrivate::ObjectDeleter;
307 using ::BPrivate::ArrayDeleter;
308 using ::BPrivate::MemoryDeleter;
309 using ::BPrivate::CObjectDeleter;
310 using ::BPrivate::MethodDeleter;
311 using ::BPrivate::HandleDeleter;
312 using ::BPrivate::FileDescriptorCloser;
313 
314 
315 #endif	// _AUTO_DELETER_H
316