// Copyright (c) 2004, Eugene Gershnik // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef HEADER_REFCNT_PTR_H #define HEADER_REFCNT_PTR_H // // refcnt_ptr // An intrusive reference counting smart pointer class template // see http://www.gershnik.com/articles/refcnt_ptr.asp for details // template struct attachment_data { T * p; }; template struct reference_data { T * p; }; template attachment_data noref(T * p) { const attachment_data ret = {p}; return ret; } template reference_data ref(T * p) { const reference_data ret = {p}; return ret; } template class refcnt_ptr { private: struct dummy { int i; }; typedef int dummy::*_bool; public: refcnt_ptr() : m_p(0) {} refcnt_ptr(const refcnt_ptr & src) : m_p(src.m_p) { this->do_add_ref(m_p); } refcnt_ptr & operator=(const refcnt_ptr & src) { refcnt_ptr temp(src); this->swap(temp); return *this; } template refcnt_ptr(const refcnt_ptr & src) : m_p(src.c_ptr()) { this->do_add_ref(m_p); } template refcnt_ptr & operator=(const refcnt_ptr & src) { refcnt_ptr temp(src); this->swap(temp); return *this; } //Attachment and reference to a raw pointer template refcnt_ptr(const attachment_data & src) : m_p(src.p) { } template refcnt_ptr & operator=(const attachment_data & src) { refcnt_ptr temp(src); this->swap(temp); return *this; } template refcnt_ptr(const reference_data & src) : m_p(src.p) { this->do_add_ref(m_p); } template refcnt_ptr & operator=(const reference_data & src) { refcnt_ptr temp(src); this->swap(temp); return *this; } ~refcnt_ptr() { this->reset(); } T * operator->() const { return m_p; } T & operator*() const { return *m_p; } T * c_ptr() const { return m_p; } operator _bool() const { return m_p ? &dummy::i: 0; } T * release() { T * p = m_p; m_p = 0; return p; } void reset() { this->do_sub_ref(m_p); m_p = 0; } void swap(refcnt_ptr & other) { T * temp = m_p; m_p = other.m_p; other.m_p = temp; } private: static void do_add_ref(T * p) { typedef char dummy[sizeof(T)]; if (p) refcnt_add_ref(*p); } static void do_sub_ref(T * p) { typedef char dummy[sizeof(T)]; if (p) refcnt_sub_ref(*p); } private: T * m_p; }; template bool operator==(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return lhs.c_ptr() == rhs.c_ptr(); } template bool operator==(const refcnt_ptr & lhs, const Y * rhs) { return lhs.c_ptr() == rhs; } template bool operator==(const Y * lhs, const refcnt_ptr & rhs) { return lhs == rhs.c_ptr(); } template bool operator!=(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return !(lhs == rhs); } template bool operator!=(const refcnt_ptr & lhs, const Y * rhs) { return !(lhs == rhs); } template bool operator!=(const Y * lhs, const refcnt_ptr & rhs) { return !(lhs == rhs); } template bool operator<(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return lhs.c_ptr() < rhs.c_ptr(); } template bool operator<(const refcnt_ptr & lhs, const Y * rhs) { return lhs.c_ptr() < rhs; } template bool operator<(const Y * lhs, const refcnt_ptr & rhs) { return lhs < rhs.c_ptr(); } template bool operator<=(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return lhs.c_ptr() <= rhs.c_ptr(); } template bool operator<=(const refcnt_ptr & lhs, const Y * rhs) { return lhs.c_ptr() <= rhs; } template bool operator<=(const Y * lhs, const refcnt_ptr & rhs) { return lhs <= rhs.c_ptr(); } template bool operator>(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return !(lhs <= rhs); } template bool operator>(const refcnt_ptr & lhs, const Y * rhs) { return !(lhs <= rhs); } template bool operator>(const Y * lhs, const refcnt_ptr & rhs) { return !(lhs <= rhs); } template bool operator>=(const refcnt_ptr & lhs, const refcnt_ptr & rhs) { return !(lhs < rhs); } template bool operator>=(const refcnt_ptr & lhs, const Y * rhs) { return !(lhs < rhs); } template bool operator>=(const Y * lhs, const refcnt_ptr & rhs) { return !(lhs < rhs); } template inline refcnt_ptr refcnt_const_cast(const refcnt_ptr & p) { return refcnt_ptr(ref(const_cast(p.c_ptr()))); } template inline refcnt_ptr refcnt_dynamic_cast(const refcnt_ptr & p) { return refcnt_ptr(ref(dynamic_cast(p.c_ptr()))); } template inline refcnt_ptr refcnt_reinterpret_cast(const refcnt_ptr & p) { return refcnt_ptr(ref(reinterpret_cast(p.c_ptr()))); } template inline refcnt_ptr refcnt_static_cast(const refcnt_ptr & p) { return refcnt_ptr(ref(static_cast(p.c_ptr()))); } #endif //HEADER_REFCNT_PTR_H