2008-01-08 10:51:28 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
2009-02-03 12:01:46 +00:00
|
|
|
// Name: wx/sharedptr.h
|
2008-01-08 10:51:28 +00:00
|
|
|
// Purpose: Shared pointer based on the counted_ptr<> template, which
|
|
|
|
// is in the public domain
|
|
|
|
// Author: Robert Roebling, Yonat Sharon
|
|
|
|
// Copyright: Robert Roebling
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2009-02-03 12:01:46 +00:00
|
|
|
#ifndef _WX_SHAREDPTR_H_
|
|
|
|
#define _WX_SHAREDPTR_H_
|
2008-01-08 10:51:28 +00:00
|
|
|
|
|
|
|
#include "wx/defs.h"
|
|
|
|
#include "wx/atomic.h"
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxSharedPtr: A smart pointer with non-intrusive reference counting.
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2009-02-03 12:01:46 +00:00
|
|
|
template <class T>
|
2008-01-08 10:51:28 +00:00
|
|
|
class wxSharedPtr
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef T element_type;
|
|
|
|
|
2016-08-30 08:44:32 +00:00
|
|
|
explicit wxSharedPtr( T* ptr = NULL )
|
2009-02-03 12:01:46 +00:00
|
|
|
: m_ref(NULL)
|
|
|
|
{
|
|
|
|
if (ptr)
|
|
|
|
m_ref = new reftype(ptr);
|
2008-01-08 10:51:28 +00:00
|
|
|
}
|
2009-02-03 12:01:46 +00:00
|
|
|
|
2013-09-06 17:09:11 +00:00
|
|
|
template<typename Deleter>
|
2016-08-30 08:44:32 +00:00
|
|
|
explicit wxSharedPtr(T* ptr, Deleter d)
|
2013-09-06 17:09:11 +00:00
|
|
|
: m_ref(NULL)
|
|
|
|
{
|
|
|
|
if (ptr)
|
|
|
|
m_ref = new reftype_with_deleter<Deleter>(ptr, d);
|
|
|
|
}
|
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
~wxSharedPtr() { Release(); }
|
|
|
|
wxSharedPtr(const wxSharedPtr& tocopy) { Acquire(tocopy.m_ref); }
|
2009-02-03 12:01:46 +00:00
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
wxSharedPtr& operator=( const wxSharedPtr& tocopy )
|
|
|
|
{
|
2009-02-03 12:01:46 +00:00
|
|
|
if (this != &tocopy)
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
|
|
|
Release();
|
|
|
|
Acquire(tocopy.m_ref);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSharedPtr& operator=( T* ptr )
|
|
|
|
{
|
2009-02-03 12:01:46 +00:00
|
|
|
if (get() != ptr)
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
|
|
|
Release();
|
2009-02-03 12:01:46 +00:00
|
|
|
if (ptr)
|
|
|
|
m_ref = new reftype(ptr);
|
2008-01-08 10:51:28 +00:00
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2008-01-08 22:02:12 +00:00
|
|
|
// test for pointer validity: defining conversion to unspecified_bool_type
|
|
|
|
// and not more obvious bool to avoid implicit conversions to integer types
|
|
|
|
typedef T *(wxSharedPtr<T>::*unspecified_bool_type)() const;
|
|
|
|
operator unspecified_bool_type() const
|
|
|
|
{
|
|
|
|
if (m_ref && m_ref->m_ptr)
|
|
|
|
return &wxSharedPtr<T>::get;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
T& operator*() const
|
2009-02-03 12:01:46 +00:00
|
|
|
{
|
|
|
|
wxASSERT(m_ref != NULL);
|
|
|
|
wxASSERT(m_ref->m_ptr != NULL);
|
2008-01-08 10:51:28 +00:00
|
|
|
return *(m_ref->m_ptr);
|
|
|
|
}
|
2009-02-03 12:01:46 +00:00
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
T* operator->() const
|
2009-02-03 12:01:46 +00:00
|
|
|
{
|
|
|
|
wxASSERT(m_ref != NULL);
|
|
|
|
wxASSERT(m_ref->m_ptr != NULL);
|
2008-01-08 10:51:28 +00:00
|
|
|
return m_ref->m_ptr;
|
|
|
|
}
|
2009-02-03 12:01:46 +00:00
|
|
|
|
|
|
|
T* get() const
|
|
|
|
{
|
|
|
|
return m_ref ? m_ref->m_ptr : NULL;
|
2008-01-08 10:51:28 +00:00
|
|
|
}
|
2009-02-03 12:01:46 +00:00
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
void reset( T* ptr = NULL )
|
|
|
|
{
|
|
|
|
Release();
|
2009-02-03 12:01:46 +00:00
|
|
|
if (ptr)
|
|
|
|
m_ref = new reftype(ptr);
|
2008-01-08 10:51:28 +00:00
|
|
|
}
|
2009-02-03 12:01:46 +00:00
|
|
|
|
2013-09-06 17:09:11 +00:00
|
|
|
template<typename Deleter>
|
|
|
|
void reset(T* ptr, Deleter d)
|
|
|
|
{
|
|
|
|
Release();
|
|
|
|
if (ptr)
|
|
|
|
m_ref = new reftype_with_deleter<Deleter>(ptr, d);
|
|
|
|
}
|
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
bool unique() const { return (m_ref ? m_ref->m_count == 1 : true); }
|
|
|
|
long use_count() const { return (m_ref ? (long)m_ref->m_count : 0); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2009-02-03 12:01:46 +00:00
|
|
|
struct reftype
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
2013-09-06 17:09:11 +00:00
|
|
|
reftype(T* ptr) : m_ptr(ptr), m_count(1) {}
|
|
|
|
virtual ~reftype() {}
|
|
|
|
virtual void delete_ptr() { delete m_ptr; }
|
|
|
|
|
2008-01-08 10:51:28 +00:00
|
|
|
T* m_ptr;
|
|
|
|
wxAtomicInt m_count;
|
2013-09-06 17:09:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Deleter>
|
|
|
|
struct reftype_with_deleter : public reftype
|
|
|
|
{
|
|
|
|
reftype_with_deleter(T* ptr, Deleter d) : reftype(ptr), m_deleter(d) {}
|
|
|
|
virtual void delete_ptr() { m_deleter(this->m_ptr); }
|
|
|
|
|
|
|
|
Deleter m_deleter;
|
|
|
|
};
|
|
|
|
|
|
|
|
reftype* m_ref;
|
2008-01-08 10:51:28 +00:00
|
|
|
|
2009-02-03 12:01:46 +00:00
|
|
|
void Acquire(reftype* ref)
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
|
|
|
m_ref = ref;
|
2009-02-03 12:01:46 +00:00
|
|
|
if (ref)
|
2008-01-08 10:51:28 +00:00
|
|
|
wxAtomicInc( ref->m_count );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Release()
|
|
|
|
{
|
2009-02-03 12:01:46 +00:00
|
|
|
if (m_ref)
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
2013-05-31 23:20:58 +00:00
|
|
|
if (!wxAtomicDec( m_ref->m_count ))
|
2008-01-08 10:51:28 +00:00
|
|
|
{
|
2013-09-06 17:09:11 +00:00
|
|
|
m_ref->delete_ptr();
|
2008-01-08 10:51:28 +00:00
|
|
|
delete m_ref;
|
|
|
|
}
|
|
|
|
m_ref = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T, class U>
|
|
|
|
bool operator == (wxSharedPtr<T> const &a, wxSharedPtr<U> const &b )
|
|
|
|
{
|
|
|
|
return a.get() == b.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, class U>
|
|
|
|
bool operator != (wxSharedPtr<T> const &a, wxSharedPtr<U> const &b )
|
|
|
|
{
|
|
|
|
return a.get() != b.get();
|
|
|
|
}
|
|
|
|
|
2009-02-03 12:01:46 +00:00
|
|
|
#endif // _WX_SHAREDPTR_H_
|