Download | Plain Text | Line Numbers


/**
 * @module shared_ptr
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  Class template shared_ptr
 * @date   13.06.2009
 */
 
#ifndef SHARED_PTR_H
#define SHARED_PTR_H
 
#include <algorithm>
 
#undef SOLVED_1
#define SOLVED_1
 
namespace Ti
{
  /**
   * @class shared_ptr
   *
   * The templates stores a pointer, usually obtained via new.
   * shared_ptr implements semantics of shared ownership; the last remaining
   * owner of the pointer is responsible for destroying the object, or
   * otherwise releasing the resources associated with the stored pointer.
   * A shared_ptr object is empty if it does not own a pointer.
   */
  template <typename T>
    class shared_ptr
    {
      private:
        /** stored pointer */
        T* m_ptr;
        /** reference counter */
        unsigned long* m_count;
 
      public:
        /**
         * @method shared_ptr
         * @brief  Default ctor
         * @param  -
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post get() == m_count == NULL
         */
        shared_ptr()
          : m_ptr(NULL), m_count(NULL)
        {}
 
        /**
         * @method get
         * @brief  Returns pointer of enclosed object
         * @param  -
         * @return returns the stored pointer, null pointer if *this is empty.
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        T* get() const
        {
          return m_ptr;
        }
 
        /**
         * @method shared_ptr
         * @brief  Copy ctor.  If r is empty, constructs an empty shared_ptr
         *         object - otherwise, constructs a shared_ptr object that
         *         shares ownership with r.
         * @param  other  instance to copy from
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post get() == other.get() && m_count == other.m_count
         */
        shared_ptr(const shared_ptr<T>& other)
          : m_ptr(other.m_ptr), m_count(other.m_count)
        {
          add_ref();
        }
 
        /**
         * @method shared_ptr
         * @brief  Copy ctor. If other is empty, constructs an empty shared_ptr
         *         object - otherwise, constructs a shared_ptr object that
         *         shares ownership with other.
         * @param  other  instance to copy from
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  The constructor shall not participate in the overload
         *       resolution unless O* is implicitly convertible to T*.
         * @post get() == other.get() && m_count == other.m_count
         */
        template <typename O>
          shared_ptr(const shared_ptr<O>& other)
            : m_ptr(other.m_ptr), m_count(other.m_count)
          {
            add_ref();
          }
 
        /**
         * @method shared_ptr
         * @brief  Copy ctor. Constructs a shared_ptr instance that stores ptr
         *         and shares ownership with other.
         * @param  other  instance to copy from
         * @param  ptr    ptr to store
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post get() == p && m_count == other.m_count
         */
        template <typename O>
          shared_ptr(const shared_ptr<O>& other, T* ptr)
            : m_ptr(ptr), m_count(other.m_count)
          {
            add_ref();
          }
 
        /**
         * @method shared_ptr
         * @brief  Copy ctor. Constructs a shared_ptr object that owns the pointer p.
         * @param  p  pointer to store
         * @return -
         * @globalvars none
         * @exception  bad_alloc if memory couldn't be optained
         * @pre  p shall be convertible to T*. Y shall be a complete type. The
         *       expression delete p shall be well formed, shall have well
         *       defined behavior, and shall not throw exceptions.
         * @post get() == p && m_count == 1
         */
        template <typename O>
          explicit shared_ptr(O* p)
          : m_ptr(p), m_count(new unsigned long(1))
          {}
 
        /**
         * @method operator=
         * @brief  operator =
         * @param  other  object to compare with
         * @return always *this
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        shared_ptr& operator=(const shared_ptr<T>& other)
        {
          if (*this == other)
            return *this;
          release();
          m_ptr = other.m_ptr;
          m_count = other.m_count;
          add_ref();
          return *this;
        }
 
        /**
         * @method operator=
         * @brief  operator =
         * @param  other  object to compare with
         * @return always *this
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        template <typename O>
          shared_ptr& operator=(const shared_ptr<O>& other)
        {
          if (*this == other)
            return *this;
          release();
          m_ptr = other.m_ptr;
          m_count = other.m_count;
          add_ref();
          return *this;
        }
 
        /**
         * @method ~shared_ptr
         * @brief  Dtor
         * @param  -
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        ~shared_ptr()
        {
          release();
        }
 
        /**
         * @method operator*
         * @brief  operator *
         * @param  -
         * @return returns *get()
         * @globalvars none
         * @exception  none
         * @pre  get() != NULL
         * @post none
         */
        T& operator*() const
        {
          return *m_ptr;
        }
 
        /**
         * @method operator->
         * @brief  operator ->
         * @param  -
         * @return returns get()
         * @globalvars none
         * @exception  none
         * @pre  get() != NULL
         * @post none
         */
        T* operator->() const
        {
          return m_ptr;
        }
 
        /**
         * @method swap
         * @brief  Exchanges the contents of *this and other.
         * @param  other  instance to swap with
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        void swap(shared_ptr<T>& other)
        {
          std::swap(m_ptr, other.m_ptr);
          std::swap(m_count, other.m_count);
        }
 
        /**
         * @method reset
         * @brief  Equivalent to shared_ptr().swap(*this).
         * @param  -
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  none
         * @post none
         */
        inline void reset()
        {
          shared_ptr().swap(*this);
        }
 
      private:
        /**
         * @method add_ref
         * @brief  Increase reference counter
         * @param  -
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  m_count != NULL
         * @post none
         */
        void add_ref()
        {
          if (m_count != NULL)
            ++(*m_count);
        }
 
        /**
         * @method release
         * @brief  Decrease reference counter
         *         if m_count == 0 free all resources
         * @param  -
         * @return -
         * @globalvars none
         * @exception  none
         * @pre  m_ptr != NULL && m_count != NULL
         * @post none
         */
        void release()
        {
          if (m_ptr != NULL)
          {
            --(*m_count);
            if (*m_count == 0)
            {
              delete m_ptr;
              delete m_count;
            }
          }
        }
 
        template<class O> friend class shared_ptr;
 
        template <typename R, typename... Args>
          friend shared_ptr<R> make_shared(Args...);
 
        template<typename U1, typename U2>
          friend bool operator==(const shared_ptr<U1>& a, const shared_ptr<U2>& b);
 
        template<typename U1, typename U2>
          friend bool operator==(const shared_ptr<U1>& a, const U2* b);
 
        template<typename U1, typename U2>
          friend bool operator==(const U1* a, const shared_ptr<U2>& b);
 
        template<typename U1, typename U2>
          friend bool operator!=(const shared_ptr<U1>& a, const U2* b);
 
        template<typename U1, typename U2>
          friend bool operator!=(const U1* a, const shared_ptr<U2>& b);
 
        template<typename U1, typename U2>
          friend bool operator!=(const shared_ptr<U1>& a, const shared_ptr<U2>& b);
 
        template <typename R, typename F>
          friend shared_ptr<R> shared_dynamic_cast(const shared_ptr<F>& from);
    };
 
  /**
   * @method make_shared
   * @brief  Creates an instance of shared_ptr containing a pointer to the
   *         also created instance of T(args...).
   * @param  args  arguments for ctor of T.
   * @return A shared_ptr instance that stores and owns the address of the
   *         newly constructed object of type T.
   * @globalvars none
   * @exception  bad_alloc
   * @pre  none
   * @post get() != 0 && use_count() == 1
   */
  template <typename T, typename ... Args>
    shared_ptr<T> make_shared(Args ... args)
    {
      return shared_ptr<T>(new T(args ...));
    }
 
  /**
   * @method operator==
   * @brief  operator ==
   * @param  a  object1 to compare
   * @param  b  object2 to compare
   * @return true if both objects contain the same pointer, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator==(const shared_ptr<U1>& a, const shared_ptr<U2>& b)
    {
      return a.get() == b.get();
    }
 
  /**
   * @method operator==
   * @brief  operator ==
   * @param  a  shared_ptr to compare
   * @param  b  pointer to compare
   * @return true if a contains pointer b, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator==(const shared_ptr<U1>& a, const U2* b)
    {
      return a.get() == b;
    }
 
  /**
   * @method operator==
   * @brief  operator ==
   * @param  a  pointer to compare
   * @param  b  shared_ptr to compare
   * @return true if b contains pointer a, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator==(const U1* a, const shared_ptr<U2>& b)
    {
      return a == b.get();
    }
 
  /**
   * @method operator!=
   * @brief  operator !=
   * @param  a  shared_ptr to compare
   * @param  b  pointer to compare
   * @return true if a contains different pointer than b, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator!=(const shared_ptr<U1>& a, const U2* b)
    {
      return a.get() != b;
    }
 
  /**
   * @method operator!=
   * @brief  operator !=
   * @param  a  pointer to compare
   * @param  b  shared_ptr to compare
   * @return true if b contains different pointer than a, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator!=(const U1* a, const shared_ptr<U2>& b)
    {
      return a != b.get();
    }
 
  /**
   * @method operator!=
   * @brief  operator !=
   * @param  a  object1 to compare
   * @param  b  object2 to compare
   * @return true if both objects contain different pointers, false otherwise.
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template<typename U1, typename U2>
    bool operator!=(const shared_ptr<U1>& a, const shared_ptr<U2>& b)
    {
      return a.get() != b.get();
    }
 
  /**
   * @method shared_dynamic_cast
   * @brief  Converts pointer from F to T by using dynamic_cast.
   * @param  from  object to cast
   * @return When dynamic_cast<T*>(from.get()) returns a nonzero value,
   *         a shared_ptr<T> object that stores a copy of it and shares
   *         ownership with from - otherwise an empty shared_ptr<T> object.
   * @globalvars none
   * @exception  none
   * @pre  The expression shared_dynamic_cast<T*>(from.get()) shall be well
   *       formed and shall have well defined behavior.
   * @post w.get() == dynamic_cast<T*>(from.get()), where w is the return value.
   */
  template <typename T, typename F>
    shared_ptr<T> shared_dynamic_cast(const shared_ptr<F>& from)
    {
      T* castptr = dynamic_cast<T *>(from.get());
      if (castptr != NULL)
        return shared_ptr<T>(from, castptr);
      else
        return shared_ptr<T>();
    }
} // end namespace ti
 
namespace std
{
  using namespace Ti;
 
  /**
   * @method swap
   * @brief  Exchanges the contents of t1 and t2.
   * @param  t1  instance#1 of shared_ptr
   * @param  t2  instance#2 of shared_ptr
   * @return -
   * @globalvars none
   * @exception  none
   * @pre  none
   * @post none
   */
  template <typename T>
    inline void swap(shared_ptr<T>& t1, shared_ptr<T>& t2)
    {
      t1.swap(t2);
    }
}
 
#endif
 
/* vim: set et sw=2 ts=2: */