#ifndef SHARED_PTR_H #define SHARED_PTR_H /* TODO includes */ #undef SOLVED_1 #define SOLVED_1 /* TODO: remove */ #define SHPDEBUG if (0) #include namespace Ti { /* TODO helpers */ template class shared_ptr { private: T* m_ptr; unsigned long* m_count; public: shared_ptr() : m_ptr(NULL), m_count(NULL) { SHPDEBUG std::cerr << this << ": shared_ptr()" << std::endl; } T* get() const { SHPDEBUG std::cerr << this << ": get()" << std::endl; return m_ptr; } shared_ptr(const shared_ptr& other) : m_ptr(other.m_ptr), m_count(other.m_count) { SHPDEBUG std::cerr << this << ": shared_ptr(shared_ptr& other)" << std::endl; add_ref(); } template shared_ptr(const shared_ptr& other) : m_ptr(other.m_ptr), m_count(other.m_count) { SHPDEBUG std::cerr << this << ": shared_ptr(shared_ptr& other)" << std::endl; add_ref(); } /* used to construct shared_ptr with a sub-object of O */ template shared_ptr(const shared_ptr& other, T* ptr) : m_ptr(ptr), m_count(other.m_count) { SHPDEBUG std::cerr << this << ": shared_ptr(shared_ptr& other, O* ptr)" << std::endl; add_ref(); } template explicit shared_ptr(O* p) : m_ptr(p), m_count(new unsigned long(1)) { SHPDEBUG std::cerr << this << ": shared_ptr(O* p)" << std::endl; } shared_ptr& operator=(const shared_ptr& other) { SHPDEBUG std::cerr << this << ": operator=(shared_ptr& other)" << std::endl; #if 1 shared_ptr(other).swap(*this); return *this; #else if (*this == other) return *this; release(); m_ptr = other.m_ptr; m_count = other.m_count; add_ref(); return *this; #endif } template shared_ptr& operator=(const shared_ptr& other) { SHPDEBUG std::cerr << this << ": operator=(shared_ptr& other)" << std::endl; #if 0 shared_ptr(other).swap(*this); return *this; #else if (*this == other) return *this; release(); m_ptr = other.m_ptr; m_count = other.m_count; add_ref(); return *this; #endif } ~shared_ptr() { SHPDEBUG std::cerr << this << ": ~shared_ptr()" << std::endl; release(); } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } void swap(shared_ptr& other) { /* std::swap(m_ptr, other.m_ptr); */ T* ptr(m_ptr); m_ptr = other.m_ptr; other.m_ptr = ptr; /* std::swap(m_count, other.m_count); */ unsigned long* count(m_count); m_count = other.m_count; other.m_count = count; } inline void reset() { shared_ptr().swap(*this); } private: void add_ref() { if (m_count != NULL) ++(*m_count); } 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); }; template shared_ptr make_shared(Args ... args) { SHPDEBUG std::cerr << "make_shared(args...)" << std::endl; return shared_ptr(new T(args ...)); } template bool operator==(const shared_ptr& a, const shared_ptr& b) { return a.get() == b.get(); } template bool operator==(const shared_ptr& a, const U2* b) { return a.get() == b.get(); } template bool operator==(const U1* a, const shared_ptr& b) { return a.get() == b.get(); } template bool operator!=(const shared_ptr& a, const U2* b) { return a.get() != b.get(); } template bool operator!=(const U1* a, const shared_ptr& b) { return a.get() != b.get(); } template bool operator!=(const shared_ptr& a, const shared_ptr& b) { return a.get() != b.get(); } template shared_ptr shared_dynamic_cast(const shared_ptr& from) { SHPDEBUG std::cerr << "shared_dynamic_cast(...)" << std::endl; 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; template inline void swap(shared_ptr& t1, shared_ptr& t2) { t1.swap(t2); } /* TODO */ } #endif /* vim: set et sw=2 ts=2: */