VirtualBox

root/trunk/include/iprt/cpputils.h

Revision 13926, 12.5 kB (checked in by vboxsync, 2 weeks ago)

Correct a few minor typos in comments. No content changes.

  • Property svn:eol-style set to native
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  */
53 template <class C>
54 inline 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  */
68 template <class C>
69 inline C *unconst (const C *that) { return const_cast <C *> (that); }
70
71
72 /**
73  * Extensions to the std namespace.
74  */
75 namespace stdx
76 {
77
78 /* forward */
79 template <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  */
89 class auto_ref
90 {
91 protected:
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
101 private:
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  */
132 template <class C>
133 class auto_ref_ptr
134 {
135 public:
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
216 protected:
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  */
251 class exception_trap_base
252 {
253 public:
254
255     virtual void rethrow() = 0;
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  */
313 template <typename T>
314 class exception_trap : public exception_trap_base
315 {
316 public:
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  */
345 template <typename T>
346 static exception_trap <T> *
347 new_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  */
367 class char_auto_ptr : public std::auto_ptr <char>
368 {
369 public:
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  */
405 class non_copyable
406 {
407 protected:
408     non_copyable() {}
409     ~non_copyable() {}
410 private:
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 browser.

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy