/** * @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 #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 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& 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 shared_ptr(const shared_ptr& 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 shared_ptr(const shared_ptr& 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 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& 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 shared_ptr& operator=(const shared_ptr& 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& 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 friend class shared_ptr; template friend shared_ptr make_shared(Args...); template friend bool operator==(const shared_ptr& a, const shared_ptr& b); template friend bool operator==(const shared_ptr& a, const U2* b); template friend bool operator==(const U1* a, const shared_ptr& b); template friend bool operator!=(const shared_ptr& a, const U2* b); template friend bool operator!=(const U1* a, const shared_ptr& b); template friend bool operator!=(const shared_ptr& a, const shared_ptr& b); template friend shared_ptr shared_dynamic_cast(const shared_ptr& 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 shared_ptr make_shared(Args ... args) { return shared_ptr(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 bool operator==(const shared_ptr& a, const shared_ptr& 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 bool operator==(const shared_ptr& 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 bool operator==(const U1* a, const shared_ptr& 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 bool operator!=(const shared_ptr& 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 bool operator!=(const U1* a, const shared_ptr& 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 bool operator!=(const shared_ptr& a, const shared_ptr& 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(from.get()) returns a nonzero value, * a shared_ptr object that stores a copy of it and shares * ownership with from - otherwise an empty shared_ptr object. * @globalvars none * @exception none * @pre The expression shared_dynamic_cast(from.get()) shall be well * formed and shall have well defined behavior. * @post w.get() == dynamic_cast(from.get()), where w is the return value. */ template shared_ptr shared_dynamic_cast(const shared_ptr& from) { T* castptr = dynamic_cast(from.get()); if (castptr != NULL) return shared_ptr(from, castptr); else return shared_ptr(); } } // 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 inline void swap(shared_ptr& t1, shared_ptr& t2) { t1.swap(t2); } } #endif /* vim: set et sw=2 ts=2: */