VirtualBox

source: vbox/trunk/include/iprt/cpputils.h@ 21751

Last change on this file since 21751 was 18467, checked in by vboxsync, 16 years ago

cpptuils.h: Fixed no virtual destructor warning.

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1/** @file
2 * IPRT - C++ Utilities (useful templates, defines and such).
3 */
4
5/*
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 *
25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
27 * additional information or have any questions.
28 */
29
30#ifndef ___iprt_cpputils_h
31#define ___iprt_cpputils_h
32
33#include <iprt/assert.h>
34
35#include <memory>
36
37/** @defgroup grp_rt_cpputils C++ Utilities
38 * @ingroup grp_rt
39 * @{
40 */
41
42/**
43 * Shortcut to |const_cast<C &>()| that automatically derives the correct
44 * type (class) for the const_cast template's argument from its own argument.
45 * Can be used to temporarily cancel the |const| modifier on the left-hand side
46 * of assignment expressions, like this:
47 * @code
48 * const Class that;
49 * ...
50 * unconst (that) = some_value;
51 * @endcode
52 */
53template <class C>
54inline C &unconst (const C &that) { return const_cast <C &> (that); }
55
56
57/**
58 * Shortcut to |const_cast<C *>()| that automatically derives the correct
59 * type (class) for the const_cast template's argument from its own argument.
60 * Can be used to temporarily cancel the |const| modifier on the left-hand side
61 * of assignment expressions, like this:
62 * @code
63 * const Class *that;
64 * ...
65 * unconst (that) = some_value;
66 * @endcode
67 */
68template <class C>
69inline C *unconst (const C *that) { return const_cast <C *> (that); }
70
71
72/**
73 * Extensions to the std namespace.
74 */
75namespace stdx
76{
77
78/* forward */
79template <class> class auto_ref_ptr;
80
81/**
82 * Base class for objects willing to support smart reference counting using
83 * the auto_ref_ptr template.
84 *
85 * When a class wants to be used with the auto_ref_ptr template it simply
86 * declares the auto_ref class among its public base classes -- there is no
87 * need to implement any additional methods.
88 */
89class auto_ref
90{
91protected:
92
93 auto_ref() : mRefs (0) {}
94
95 /** Increases the reference counter and returns it */
96 size_t ref() { return ++ mRefs; }
97
98 /** Decreases the reference counter and returns it */
99 size_t unref() { Assert (mRefs > 0); return -- mRefs; }
100
101private:
102
103 size_t mRefs;
104
105 template <class> friend class auto_ref_ptr;
106};
107
108/**
109 * The auto_ref_ptr template manages pointers to objects that support
110 * reference counting by implementing auto_ref or a similar interface.
111 *
112 * Pointer management includes the following key points:
113 *
114 * 1) Automatic increment of the object's reference counter when the given
115 * auto_ref_ptr instance starts managing a pointer to this object.
116 *
117 * 2) Automatic decrement of the reference counter when the given
118 * auto_ref_ptr instance is destroyed, or before it is assigned a pointer
119 * to a new object.
120 *
121 * 3) Automatic deletion of the managed object whenever its reference
122 * counter reaches zero after a decrement.
123 *
124 * 4) Providing the dereference operator-> that gives direct access to the
125 * managed pointer.
126 *
127 * The object class to manage must provide ref() and unref() methods that have
128 * the same syntax and semantics as defined in the auto_ref class.
129 *
130 * @param C Class to manage.
131 */
132template <class C>
133class auto_ref_ptr
134{
135public:
136
137 /**
138 * Creates a null instance that does not manage anything.
139 */
140 auto_ref_ptr() : m (NULL) {}
141
142 /**
143 * Creates an instance that starts managing the given pointer. The
144 * reference counter of the object pointed to by @a a is incremented by
145 * one.
146 *
147 * @param a Pointer to manage.
148 */
149 auto_ref_ptr (C* a) : m (a) { if (m) m->ref(); }
150
151 /**
152 * Creates an instance that starts managing a pointer managed by the given
153 * instance. The reference counter of the object managed by @a that is
154 * incremented by one.
155 *
156 * @param that Instance to take a pointer to manage from.
157 */
158 auto_ref_ptr (const auto_ref_ptr &that) : m (that.m) { if (m) m->ref(); }
159
160 ~auto_ref_ptr() { do_unref(); }
161
162 /**
163 * Assigns the given pointer to this instance and starts managing it. The
164 * reference counter of the object pointed to by @a a is incremented by
165 * one. The reference counter of the object previously managed by this
166 * instance is decremented by one.
167 *
168 * @param a Pointer to assign.
169 */
170 auto_ref_ptr &operator= (C *a) { do_reref (a); return *this; }
171
172 /**
173 * Assigns a pointer managed by the given instance to this instance and
174 * starts managing it. The reference counter of the object managed by @a
175 * that is incremented by one. The reference counter of the object
176 * previously managed by this instance is decremented by one.
177 *
178 * @param that Instance which pointer to reference.
179 */
180 auto_ref_ptr &operator= (const auto_ref_ptr &that) { do_reref (that.m); return *this; }
181
182 /**
183 * Returns @c true if this instance is @c null and false otherwise.
184 */
185 bool is_null() const { return m == NULL; }
186
187 /**
188 * Dereferences the instance by returning the managed pointer.
189 * Asserts that the managed pointer is not @c NULL.
190 */
191 C *operator-> () const { AssertMsg (m, ("Managed pointer is NULL!\n")); return m; }
192
193 /**
194 * Returns the managed pointer or @c NULL if this instance is @c null.
195 */
196 C *raw() const { return m; }
197
198 /**
199 * Compares this auto_ref_ptr instance with another instance and returns
200 * @c true if both instances manage the same or @c NULL pointer.
201 *
202 * Note that this method compares pointer values only, it doesn't try to
203 * compare objects themselves. Doing otherwise would a) break the common
204 * 'pointer to something' comparison semantics auto_ref_ptr tries to
205 * follow and b) require to define the comparison operator in the managed
206 * class which is not always possible. You may analyze pointed objects
207 * yourself if you need more precise comparison.
208 *
209 * @param that Instance to compare this instance with.
210 */
211 bool operator== (const auto_ref_ptr &that) const
212 {
213 return m == that.m;
214 }
215
216protected:
217
218 void do_reref (C *a)
219 {
220 /* be aware of self assignment */
221 if (a)
222 a->ref();
223 if (m)
224 {
225 size_t refs = m->unref();
226 if (refs == 0)
227 {
228 refs = 1; /* stabilize */
229 delete m;
230 }
231 }
232 m = a;
233 }
234
235 void do_unref() { do_reref (NULL); }
236
237 C *m;
238};
239
240/**
241 * The exception_trap_base class is an abstract base class for all
242 * exception_trap template instantiations.
243 *
244 * Pointer variables of this class are used to store a pointer any object of
245 * any class instantiated from the exception_trap template, or in other words
246 * to store a full copy of any exception wrapped into the exception_trap instance
247 * allocated on the heap.
248 *
249 * See the exception_trap template for more info.
250 */
251class exception_trap_base
252{
253public:
254 virtual void rethrow() = 0;
255 virtual ~exception_trap_base() {}
256};
257
258/**
259 * The exception_trap template acts like a wrapper for the given exception
260 * class that stores a full copy of the exception and therefore allows to
261 * rethrow it preserving the actual type information about the exception
262 * class.
263 *
264 * This functionality is useful in situations where it is necessary to catch a
265 * (known) number of exception classes and pass the caught exception instance
266 * to an upper level using a regular variable (rather than the exception
267 * unwinding mechanism itself) *and* preserve all information about the type
268 * (class) of the caight exception so that it may be rethrown on the upper
269 * level unchanged.
270 *
271 * Usage pattern:
272 * @code
273 using namespace std;
274 using namespace stdx;
275
276 auto_ptr <exception_trap_base> trapped;
277
278 int callback();
279
280 int safe_callback()
281 {
282 try
283 {
284 // callback may throw a set of exceptions but we don't want it to start
285 // unwinding the stack right now
286
287 return callback();
288 }
289 catch (const MyException &err) { trapped = new_exception_trap (err); }
290 catch (const MyException2 &err) { trapped = new_exception_trap (err); }
291 catch (...) { trapped = new_exception_trap (logic_error()); }
292
293 return -1;
294 }
295
296 void bar()
297 {
298 // call a funciton from some C library that supports callbacks but knows
299 // nothing about exceptions so throwing one from a callback will leave
300 // the library in an undetermined state
301
302 do_something_with_callback (safe_callback());
303
304 // check if we have got an exeption from callback() and rethrow it now
305 // when we are not in the C library any more
306 if (trapped.get() != NULL)
307 trapped->rethrow();
308 }
309 * @endcode
310 *
311 * @param T Exception class to wrap.
312 */
313template <typename T>
314class exception_trap : public exception_trap_base
315{
316public:
317
318 exception_trap (const T &aTrapped) : trapped (aTrapped) {}
319 void rethrow() { throw trapped; }
320
321 T trapped;
322};
323
324/**
325 * Convenience function that allocates a new exception_trap instance on the
326 * heap by automatically deducing the exception_trap template argument from
327 * the type of the exception passed in @a aTrapped.
328 *
329 * The following two lines of code inside the catch block are equivalent:
330 *
331 * @code
332 using namespace std;
333 using namespace stdx;
334 catch (const MyException &err)
335 {
336 auto_ptr <exception_trap_base> t1 = new exception_trap <MyException> (err);
337 auto_ptr <exception_trap_base> t2 = new_exception_trap (err);
338 }
339 * @endcode
340 *
341 * @param aTrapped Exception to put to the allocated trap.
342 *
343 * @return Allocated exception_trap object.
344 */
345template <typename T>
346static exception_trap <T> *
347new_exception_trap (const T &aTrapped)
348{
349 return new exception_trap <T> (aTrapped);
350}
351
352/**
353 * Enhancement of std::auto_ptr @<char@> intended to take pointers to char
354 * buffers allocated using new[].
355 *
356 * This differs from std::auto_ptr @<char@> so that it overloads some methods to
357 * uses delete[] instead of delete to delete the owned data in order to
358 * conform to the C++ standard (and avoid valgrind complaints).
359 *
360 * Note that you should not use instances of this class where pointers or
361 * references to objects of std::auto_ptr @<char@> are expeced. Despite the fact
362 * the classes are related, the base is not polymorphic (in particular,
363 * neither the destructor nor the reset() method are virtual). It means that when
364 * acessing instances of this class through the base pointer, overloaded
365 * methods won't be called.
366 */
367class char_auto_ptr : public std::auto_ptr <char>
368{
369public:
370
371 explicit char_auto_ptr (char *a = 0) throw()
372 : std::auto_ptr <char> (a) {}
373
374 /* Note: we use unconst brute force below because the non-const version
375 * of the copy constructor won't accept temporary const objects
376 * (e.g. function return values) in GCC. std::auto_ptr has the same
377 * "problem" but it seems overcome it using #pragma GCC system_header
378 * which doesn't work here. */
379 char_auto_ptr (const char_auto_ptr &that) throw()
380 : std::auto_ptr <char> (unconst (that).release()) {}
381
382 ~char_auto_ptr() { delete[] (release()); }
383
384 char_auto_ptr &operator= (char_auto_ptr &that) throw()
385 {
386 std::auto_ptr <char>::operator= (that);
387 return *this;
388 }
389
390 void reset (char *a) throw()
391 {
392 if (a != get())
393 {
394 delete[] (release());
395 std::auto_ptr <char>::reset (a);
396 }
397 }
398};
399
400/**
401 * A simple class used to prevent copying and assignment. Inherit from this
402 * class in order to prevent automatic generation of the copy constructor
403 * and assignment operator in your class.
404 */
405class non_copyable
406{
407protected:
408 non_copyable() {}
409 ~non_copyable() {}
410private:
411 non_copyable(non_copyable const&);
412 non_copyable const &operator=(non_copyable const&);
413};
414
415} /* namespace stdx */
416
417/** @} */
418
419#endif
420
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette