intrusive_ptr_object.hpp
//
// Copyright (c) 2006 Alexis Wilke and Doug Barbieri
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef BOOST_INTRUSIVE_PTR_OBJECT
#define BOOST_INTRUSIVE_PTR_OBJECT 1
#include
#include
// avoid thread overhead if not required/available
#if defined(BOOST_HAS_THREADS)
#include
#endif
// place these in the boost namespace so the intrusive_ptr<> template
// finds the intrusive_ptr_add_ref() and intrusive_ptr_release() functions
// whatever the compiler. (see the boost::intrusive_ptr documentation)
//
// http://www.boost.org/libs/smart_ptr/intrusive_ptr.html
//
namespace boost
{
// objects are derived last from this class; this way they
// can be reference counted
class intrusive_ptr_object
{
public:
intrusive_ptr_object() throw()
: m_ref_count(0)
{
}
virtual ~intrusive_ptr_object() = 0;
void add_ref()
{
#if defined(BOOST_HAS_THREADS)
mutex::scoped_lock lock(m_mutex);
#endif
++m_ref_count;
}
void release()
{
#if defined(BOOST_HAS_THREADS)
mutex::scoped_lock lock(m_mutex);
#endif
// since users should not call release() themselves but use
// the intrusive_ptr<> template instead, this should never happen
BOOST_ASSERT(m_ref_count != 0);
--m_ref_count;
if(m_ref_count == 0) {
delete this;
}
}
private:
unsigned int m_ref_count;
#if defined(BOOST_HAS_THREADS)
mutex m_mutex;
#endif
};
inline intrusive_ptr_object::~intrusive_ptr_object()
{
// a stack object will be deleted without a release() call...
// if you use objects properly, this should never happen!
BOOST_ASSERT(m_ref_count == 0);
}
// All your classes derive from this class to allow for the
// dynamic_cast<> in the intrusive_ptr_add_ref() and
// intrusive_ptr_release() functions.
class intrusive_ptr_base
{
public:
// cannot instantiate
virtual ~intrusive_ptr_base() = 0;
};
inline intrusive_ptr_base::~intrusive_ptr_base()
{
}
inline void intrusive_ptr_add_ref(intrusive_ptr_base *a)
{
dynamic_cast(a)->add_ref();
}
inline void intrusive_ptr_release(intrusive_ptr_base *a)
{
dynamic_cast(a)->release();
}
// the classes you want to allocate with new and manage with
// an intrusive_ptr<> template are typedef with this template
// first, i.e.
//
// class A;
// typedef intrusive_ptr_heap A_heap;
//
template class intrusive_ptr_heap : public T, public intrusive_ptr_object {};
} // namespace boost
#endif // #ifdef BOOST_INTRUSIVE_PTR_OBJECT
// vim: ts=4