Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

cpputils.h

Go to the documentation of this file.
/** @file
 * IPRT - C++ Utilities (useful templates, defines and such).
 */

/*
 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 * additional information or have any questions.
 */

#ifndef ___iprt_cpputils_h
#define ___iprt_cpputils_h

#include <iprt/assert.h>

#include <memory>

/** @defgroup grp_rt_cpputils   C++ Utilities
 * @ingroup grp_rt
 * @{
 */

/**
 * Shortcut to |const_cast<C &>()| that automatically derives the correct
 * type (class) for the const_cast template's argument from its own argument.
 * Can be used to temporarily cancel the |const| modifier on the left-hand side
 * of assignment expressions, like this:
 * @code
 *      const Class that;
 *      ...
 *      unconst (that) = some_value;
 * @endcode
 */
template <class C>
00054 inline C &unconst (const C &that) { return const_cast <C &> (that); }


/**
 * Shortcut to |const_cast<C *>()| that automatically derives the correct
 * type (class) for the const_cast template's argument from its own argument.
 * Can be used to temporarily cancel the |const| modifier on the left-hand side
 * of assignment expressions, like this:
 * @code
 *      const Class *that;
 *      ...
 *      unconst (that) = some_value;
 * @endcode
 */
template <class C>
00069 inline C *unconst (const C *that) { return const_cast <C *> (that); }


/**
 * Extensions to the std namespace.
 */
00075 namespace stdx
{

/* forward */
template <class> class auto_ref_ptr;

/**
 * Base class for objects willing to support smart reference counting using
 * the auto_ref_ptr template.
 *
 * When a class wants to be used with the auto_ref_ptr template it simply
 * declares the auto_ref class among its public base classes -- there is no
 * need to implement any additional methods.
 */
00089 class auto_ref
{
protected:

    auto_ref() : mRefs (0) {}

    /** Increases the reference counter and returns it */
00096     size_t ref() { return ++ mRefs; }

    /** Decreases the reference counter and returns it */
00099     size_t unref() { Assert (mRefs > 0); return -- mRefs; }

private:

    size_t mRefs;

    template <class> friend class auto_ref_ptr;
};

/**
 * The auto_ref_ptr template manages pointers to objects that support
 * reference counting by implementing auto_ref or a similar interface.
 *
 * Pointer management includes the following key points:
 *
 *   1) Automatic increment of the object's reference counter when the given
 *      auto_ref_ptr instance starts managing a pointer to this object.
 *
 *   2) Automatic decrement of the reference counter when the given
 *      auto_ref_ptr instance is destroyed, or before it is assigned a pointer
 *      to a new object.
 *
 *   3) Automatic deletion of the managed object whenever its reference
 *      counter reaches zero after a decrement.
 *
 *   4) Providing the dereference operator-> that gives direct access to the
 *      managed pointer.
 *
 * The object class to manage must provide ref() and unref() methods that have
 * the same syntax and semantics as defined in the auto_ref class.
 *
 * @param C     Class to manage.
 */
template <class C>
00133 class auto_ref_ptr
{
public:

    /**
     * Creates a null instance that does not manage anything.
     */
00140     auto_ref_ptr() : m (NULL) {}

    /**
     * Creates an instance that starts managing the given pointer. The
     * reference counter of the object pointed to by @a a is incremented by
     * one.
     *
     * @param a Pointer to manage.
     */
00149     auto_ref_ptr (C* a) : m (a) { if (m) m->ref(); }

    /**
     * Creates an instance that starts managing a pointer managed by the given
     * instance. The reference counter of the object managed by @a that is
     * incremented by one.
     *
     * @param that Instance to take a pointer to manage from.
     */
00158     auto_ref_ptr (const auto_ref_ptr &that) : m (that.m) { if (m) m->ref(); }

    ~auto_ref_ptr() { do_unref(); }

    /**
     * Assigns the given pointer to this instance and starts managing it. The
     * reference counter of the object pointed to by @a a is incremented by
     * one. The reference counter of the object previously managed by this
     * instance is decremented by one.
     *
     * @param a Pointer to assign.
     */
00170     auto_ref_ptr &operator= (C *a) { do_reref (a); return *this; }

    /**
     * Assigns a pointer managed by the given instance to this instance and
     * starts managing it. The reference counter of the object managed by @a
     * that is incremented by one. The reference counter of the object
     * previously managed by this instance is decremented by one.
     *
     * @param that Instance which pointer to reference.
     */
00180     auto_ref_ptr &operator= (const auto_ref_ptr &that) { do_reref (that.m); return *this; }

    /**
     * Returns @c true if this instance is @c null and false otherwise.
     */
00185     bool is_null() const { return m == NULL; }

    /**
     * Dereferences the instance by returning the managed pointer.
     * Asserts that the managed pointer is not @c NULL.
     */
00191     C *operator-> () const { AssertMsg (m, ("Managed pointer is NULL!\n")); return m; }

    /**
     * Returns the managed pointer or @c NULL if this instance is @c null.
     */
00196     C *raw() const { return m; }

    /**
     * Compares this auto_ref_ptr instance with another instance and returns
     * @c true if both instances manage the same or @c NULL pointer.
     *
     * Note that this method compares pointer values only, it doesn't try to
     * compare objects themselves. Doing otherwise would a) break the common
     * 'pointer to something' comparison semantics auto_ref_ptr tries to
     * follow and b) require to define the comparison operator in the managed
     * class which is not always possible. You may analyze pointed objects
     * yourself if you need more precise comparison.
     *
     * @param that Instance to compare this instance with.
     */
00211     bool operator== (const auto_ref_ptr &that) const
    {
        return m == that.m;
    }

protected:

    void do_reref (C *a)
    {
        /* be aware of self assignment */
        if (a)
            a->ref();
        if (m)
        {
            size_t refs = m->unref();
            if (refs == 0)
            {
                refs = 1; /* stabilize */
                delete m;
            }
        }
        m = a;
    }

    void do_unref() { do_reref (NULL); }

    C *m;
};

/**
 * The exception_trap_base class is an abstract base class for all
 * exception_trap template instantiations.
 *
 * Pointer variables of this class are used to store a pointer any object of
 * any class instantiated from the exception_trap template, or in other words
 * to store a full copy of any exception wrapped into the exception_trap instance
 * allocated on the heap.
 *
 * See the exception_trap template for more info.
 */
00251 class exception_trap_base
{
public:
    virtual void rethrow() = 0;
    virtual ~exception_trap_base() {}
};

/**
 * The exception_trap template acts like a wrapper for the given exception
 * class that stores a full copy of the exception and therefore allows to
 * rethrow it preserving the actual type information about the exception
 * class.
 *
 * This functionality is useful in situations where it is necessary to catch a
 * (known) number of exception classes and pass the caught exception instance
 * to an upper level using a regular variable (rather than the exception
 * unwinding mechanism itself) *and* preserve all information about the type
 * (class) of the caight exception so that it may be rethrown on the upper
 * level unchanged.
 *
 * Usage pattern:
 * @code
    using namespace std;
    using namespace stdx;

    auto_ptr <exception_trap_base> trapped;

    int callback();

    int safe_callback()
    {
      try
      {
        // callback may throw a set of exceptions but we don't want it to start
        // unwinding the stack right now

        return callback();
      }
      catch (const MyException &err) { trapped = new_exception_trap (err); }
      catch (const MyException2 &err) { trapped = new_exception_trap (err); }
      catch (...) { trapped = new_exception_trap (logic_error()); }

      return -1;
    }

    void bar()
    {
      // call a funciton from some C library that supports callbacks but knows
      // nothing about exceptions so throwing one from a callback will leave
      // the library in an undetermined state

      do_something_with_callback (safe_callback());

      // check if we have got an exeption from callback() and rethrow it now
      // when we are not in the C library any more
      if (trapped.get() != NULL)
        trapped->rethrow();
    }
 * @endcode
 *
 * @param T Exception class to wrap.
 */
template <typename T>
00314 class exception_trap : public exception_trap_base
{
public:

    exception_trap (const T &aTrapped) : trapped (aTrapped) {}
    void rethrow() { throw trapped; }

    T trapped;
};

/**
 * Convenience function that allocates a new exception_trap instance on the
 * heap by automatically deducing the exception_trap template argument from
 * the type of the exception passed in @a aTrapped.
 *
 * The following two lines of code inside the catch block are equivalent:
 *
 * @code
    using namespace std;
    using namespace stdx;
    catch (const MyException &err)
    {
      auto_ptr <exception_trap_base> t1 = new exception_trap <MyException> (err);
      auto_ptr <exception_trap_base> t2 = new_exception_trap (err);
    }
 * @endcode
 *
 * @param aTrapped Exception to put to the allocated trap.
 *
 * @return Allocated exception_trap object.
 */
template <typename T>
static exception_trap <T> *
00347 new_exception_trap (const T &aTrapped)
{
    return new exception_trap <T> (aTrapped);
}

/**
 * Enhancement of std::auto_ptr @<char@> intended to take pointers to char
 * buffers allocated using new[].
 *
 * This differs from std::auto_ptr @<char@> so that it overloads some methods to
 * uses delete[] instead of delete to delete the owned data in order to
 * conform to the C++ standard (and avoid valgrind complaints).
 *
 * Note that you should not use instances of this class where pointers or
 * references to objects of std::auto_ptr @<char@> are expeced. Despite the fact
 * the classes are related, the base is not polymorphic (in particular,
 * neither the destructor nor the reset() method are virtual). It means that when
 * acessing instances of this class through the base pointer, overloaded
 * methods won't be called.
 */
00367 class char_auto_ptr : public std::auto_ptr <char>
{
public:

    explicit char_auto_ptr (char *a = 0) throw()
        : std::auto_ptr <char> (a) {}

    /* Note: we use unconst brute force below because the non-const version
     * of the copy constructor won't accept temporary const objects
     * (e.g. function return values) in GCC. std::auto_ptr has the same
     * "problem" but it seems overcome it using #pragma GCC system_header
     * which doesn't work here. */
    char_auto_ptr (const char_auto_ptr &that) throw()
        : std::auto_ptr <char> (unconst (that).release()) {}

    ~char_auto_ptr() { delete[] (release()); }

    char_auto_ptr &operator= (char_auto_ptr &that) throw()
    {
        std::auto_ptr <char>::operator= (that);
        return *this;
    }

    void reset (char *a) throw()
    {
        if (a != get())
        {
            delete[] (release());
            std::auto_ptr <char>::reset (a);
        }
    }
};

/**
 * A simple class used to prevent copying and assignment.  Inherit from this
 * class in order to prevent automatic generation of the copy constructor
 * and assignment operator in your class.
 */
00405 class non_copyable
{
protected:
    non_copyable() {}
    ~non_copyable() {}
private:
    non_copyable(non_copyable const&);
    non_copyable const &operator=(non_copyable const&);
};

} /* namespace stdx */

/** @} */

#endif


Generated by  Doxygen 1.6.0   Back to index