Changeset 30681 in vbox for trunk/include/iprt/cpp
- Timestamp:
- Jul 6, 2010 5:20:20 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/cpp/utils.h
r30676 r30681 27 27 #define ___iprt_cpputils_h 28 28 29 #include <iprt/assert.h>30 31 #include <memory>32 33 29 /** @defgroup grp_rt_cpputils C++ Utilities 34 30 * @ingroup grp_rt … … 48 44 */ 49 45 template <class C> 50 inline C &unconst (const C &that) { return const_cast <C &>(that); }46 inline C& unconst(const C &that) { return const_cast<C&>(that); } 51 47 52 48 … … 63 59 */ 64 60 template <class C> 65 inline C *unconst (const C *that) { return const_cast <C *>(that); }61 inline C* unconst(const C *that) { return const_cast<C*>(that); } 66 62 67 63 68 /** 69 * Extensions to the std namespace. 70 */ 71 namespace stdx 64 namespace iprt 72 65 { 73 74 /* forward */75 template <class> class auto_ref_ptr;76 77 /**78 * Base class for objects willing to support smart reference counting using79 * the auto_ref_ptr template.80 *81 * When a class wants to be used with the auto_ref_ptr template it simply82 * declares the auto_ref class among its public base classes -- there is no83 * need to implement any additional methods.84 */85 class auto_ref86 {87 protected:88 89 auto_ref() : mRefs (0) {}90 91 /** Increases the reference counter and returns it */92 size_t ref() { return ++ mRefs; }93 94 /** Decreases the reference counter and returns it */95 size_t unref() { Assert (mRefs > 0); return -- mRefs; }96 97 private:98 99 size_t mRefs;100 101 template <class> friend class auto_ref_ptr;102 };103 104 /**105 * The auto_ref_ptr template manages pointers to objects that support106 * reference counting by implementing auto_ref or a similar interface.107 *108 * Pointer management includes the following key points:109 *110 * 1) Automatic increment of the object's reference counter when the given111 * auto_ref_ptr instance starts managing a pointer to this object.112 *113 * 2) Automatic decrement of the reference counter when the given114 * auto_ref_ptr instance is destroyed, or before it is assigned a pointer115 * to a new object.116 *117 * 3) Automatic deletion of the managed object whenever its reference118 * counter reaches zero after a decrement.119 *120 * 4) Providing the dereference operator-> that gives direct access to the121 * managed pointer.122 *123 * The object class to manage must provide ref() and unref() methods that have124 * the same syntax and semantics as defined in the auto_ref class.125 *126 * @param C Class to manage.127 */128 template <class C>129 class auto_ref_ptr130 {131 public:132 133 /**134 * Creates a null instance that does not manage anything.135 */136 auto_ref_ptr() : m (NULL) {}137 138 /**139 * Creates an instance that starts managing the given pointer. The140 * reference counter of the object pointed to by @a a is incremented by141 * one.142 *143 * @param a Pointer to manage.144 */145 auto_ref_ptr (C* a) : m (a) { if (m) m->ref(); }146 147 /**148 * Creates an instance that starts managing a pointer managed by the given149 * instance. The reference counter of the object managed by @a that is150 * incremented by one.151 *152 * @param that Instance to take a pointer to manage from.153 */154 auto_ref_ptr (const auto_ref_ptr &that) : m (that.m) { if (m) m->ref(); }155 156 ~auto_ref_ptr() { do_unref(); }157 158 /**159 * Assigns the given pointer to this instance and starts managing it. The160 * reference counter of the object pointed to by @a a is incremented by161 * one. The reference counter of the object previously managed by this162 * instance is decremented by one.163 *164 * @param a Pointer to assign.165 */166 auto_ref_ptr &operator= (C *a) { do_reref (a); return *this; }167 168 /**169 * Assigns a pointer managed by the given instance to this instance and170 * starts managing it. The reference counter of the object managed by @a171 * that is incremented by one. The reference counter of the object172 * previously managed by this instance is decremented by one.173 *174 * @param that Instance which pointer to reference.175 */176 auto_ref_ptr &operator= (const auto_ref_ptr &that) { do_reref (that.m); return *this; }177 178 /**179 * Returns @c true if this instance is @c null and false otherwise.180 */181 bool is_null() const { return m == NULL; }182 183 /**184 * Dereferences the instance by returning the managed pointer.185 * Asserts that the managed pointer is not @c NULL.186 */187 C *operator-> () const { AssertMsg (m, ("Managed pointer is NULL!\n")); return m; }188 189 /**190 * Returns the managed pointer or @c NULL if this instance is @c null.191 */192 C *raw() const { return m; }193 194 /**195 * Compares this auto_ref_ptr instance with another instance and returns196 * @c true if both instances manage the same or @c NULL pointer.197 *198 * Note that this method compares pointer values only, it doesn't try to199 * compare objects themselves. Doing otherwise would a) break the common200 * 'pointer to something' comparison semantics auto_ref_ptr tries to201 * follow and b) require to define the comparison operator in the managed202 * class which is not always possible. You may analyze pointed objects203 * yourself if you need more precise comparison.204 *205 * @param that Instance to compare this instance with.206 */207 bool operator== (const auto_ref_ptr &that) const208 {209 return m == that.m;210 }211 212 protected:213 214 void do_reref (C *a)215 {216 /* be aware of self assignment */217 if (a)218 a->ref();219 if (m)220 {221 size_t refs = m->unref();222 if (refs == 0)223 {224 refs = 1; /* stabilize */225 delete m;226 }227 }228 m = a;229 }230 231 void do_unref() { do_reref (NULL); }232 233 C *m;234 };235 236 /**237 * The exception_trap_base class is an abstract base class for all238 * exception_trap template instantiations.239 *240 * Pointer variables of this class are used to store a pointer any object of241 * any class instantiated from the exception_trap template, or in other words242 * to store a full copy of any exception wrapped into the exception_trap instance243 * allocated on the heap.244 *245 * See the exception_trap template for more info.246 */247 class exception_trap_base248 {249 public:250 virtual void rethrow() = 0;251 virtual ~exception_trap_base() {}252 };253 254 /**255 * The exception_trap template acts like a wrapper for the given exception256 * class that stores a full copy of the exception and therefore allows to257 * rethrow it preserving the actual type information about the exception258 * class.259 *260 * This functionality is useful in situations where it is necessary to catch a261 * (known) number of exception classes and pass the caught exception instance262 * to an upper level using a regular variable (rather than the exception263 * unwinding mechanism itself) *and* preserve all information about the type264 * (class) of the caight exception so that it may be rethrown on the upper265 * level unchanged.266 *267 * Usage pattern:268 * @code269 using namespace std;270 using namespace stdx;271 272 auto_ptr <exception_trap_base> trapped;273 274 int callback();275 276 int safe_callback()277 {278 try279 {280 // callback may throw a set of exceptions but we don't want it to start281 // unwinding the stack right now282 283 return callback();284 }285 catch (const MyException &err) { trapped = new_exception_trap (err); }286 catch (const MyException2 &err) { trapped = new_exception_trap (err); }287 catch (...) { trapped = new_exception_trap (logic_error()); }288 289 return -1;290 }291 292 void bar()293 {294 // call a funciton from some C library that supports callbacks but knows295 // nothing about exceptions so throwing one from a callback will leave296 // the library in an undetermined state297 298 do_something_with_callback (safe_callback());299 300 // check if we have got an exeption from callback() and rethrow it now301 // when we are not in the C library any more302 if (trapped.get() != NULL)303 trapped->rethrow();304 }305 * @endcode306 *307 * @param T Exception class to wrap.308 */309 template <typename T>310 class exception_trap : public exception_trap_base311 {312 public:313 314 exception_trap (const T &aTrapped) : trapped (aTrapped) {}315 void rethrow() { throw trapped; }316 317 T trapped;318 };319 320 /**321 * Convenience function that allocates a new exception_trap instance on the322 * heap by automatically deducing the exception_trap template argument from323 * the type of the exception passed in @a aTrapped.324 *325 * The following two lines of code inside the catch block are equivalent:326 *327 * @code328 using namespace std;329 using namespace stdx;330 catch (const MyException &err)331 {332 auto_ptr <exception_trap_base> t1 = new exception_trap <MyException> (err);333 auto_ptr <exception_trap_base> t2 = new_exception_trap (err);334 }335 * @endcode336 *337 * @param aTrapped Exception to put to the allocated trap.338 *339 * @return Allocated exception_trap object.340 */341 template <typename T>342 static exception_trap <T> *343 new_exception_trap (const T &aTrapped)344 {345 return new exception_trap <T> (aTrapped);346 }347 348 /**349 * Enhancement of std::auto_ptr @<char@> intended to take pointers to char350 * buffers allocated using new[].351 *352 * This differs from std::auto_ptr @<char@> so that it overloads some methods to353 * uses delete[] instead of delete to delete the owned data in order to354 * conform to the C++ standard (and avoid valgrind complaints).355 *356 * Note that you should not use instances of this class where pointers or357 * references to objects of std::auto_ptr @<char@> are expeced. Despite the fact358 * the classes are related, the base is not polymorphic (in particular,359 * neither the destructor nor the reset() method are virtual). It means that when360 * acessing instances of this class through the base pointer, overloaded361 * methods won't be called.362 */363 class char_auto_ptr : public std::auto_ptr <char>364 {365 public:366 367 explicit char_auto_ptr (char *a = 0) throw()368 : std::auto_ptr <char> (a) {}369 370 /* Note: we use unconst brute force below because the non-const version371 * of the copy constructor won't accept temporary const objects372 * (e.g. function return values) in GCC. std::auto_ptr has the same373 * "problem" but it seems overcome it using #pragma GCC system_header374 * which doesn't work here. */375 char_auto_ptr (const char_auto_ptr &that) throw()376 : std::auto_ptr <char> (unconst (that).release()) {}377 378 ~char_auto_ptr() { delete[] (release()); }379 380 char_auto_ptr &operator= (char_auto_ptr &that) throw()381 {382 std::auto_ptr <char>::operator= (that);383 return *this;384 }385 386 void reset (char *a) throw()387 {388 if (a != get())389 {390 delete[] (release());391 std::auto_ptr <char>::reset (a);392 }393 }394 };395 396 66 /** 397 67 * A simple class used to prevent copying and assignment. Inherit from this … … 409 79 }; 410 80 411 } / * namespace stdx */81 } // namespace iprt 412 82 413 83 /** @} */ 414 84 415 #endif 85 #endif // ___iprt_cpputils_h 416 86
Note:
See TracChangeset
for help on using the changeset viewer.