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: */