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