nasal::Ghost: improve intrusive pointer storage and weak references.
- Just increment/decrement reference count for intrusive smart pointers. No need to create an additional object on the heap. - Keep strong reference for weak pointer based ghosts to prevent destroying objects while beeing used.
This commit is contained in:
parent
645cae184b
commit
3bbb272ad5
@ -50,12 +50,25 @@ inline T* get_pointer(SGWeakPtr<T> const& p)
|
||||
return p.lock().get();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* get_pointer(osg::observer_ptr<T> const& p)
|
||||
namespace osg
|
||||
{
|
||||
osg::ref_ptr<T> ref;
|
||||
p.lock(ref);
|
||||
return ref.get();
|
||||
template<class T>
|
||||
inline T* get_pointer(observer_ptr<T> const& p)
|
||||
{
|
||||
ref_ptr<T> ref;
|
||||
p.lock(ref);
|
||||
return ref.get();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename boost::enable_if<
|
||||
boost::is_pointer<T>,
|
||||
T
|
||||
>::type
|
||||
get_pointer(T ptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Both ways of retrieving the address of a static member function
|
||||
@ -292,9 +305,26 @@ namespace nasal
|
||||
if( !holder )
|
||||
throw std::runtime_error("holder has expired");
|
||||
|
||||
// Keep reference for duration of call to prevent expiring
|
||||
// TODO not needed for strong referenced ghost
|
||||
strong_ref ref = fromNasal<strong_ref>(c, me);
|
||||
if( !ref )
|
||||
{
|
||||
naGhostType* ghost_type = naGhost_type(me);
|
||||
naRuntimeError
|
||||
(
|
||||
c,
|
||||
"method called on object of wrong type: "
|
||||
"is '%s' expected '%s'",
|
||||
naIsNil(me) ? "nil"
|
||||
: (ghost_type ? ghost_type->name : "unknown"),
|
||||
_ghost_type_strong.name
|
||||
);
|
||||
}
|
||||
|
||||
return holder->_method
|
||||
(
|
||||
requireObject(c, me),
|
||||
*get_pointer(ref),
|
||||
CallContext(c, argc, args)
|
||||
);
|
||||
}
|
||||
@ -793,7 +823,9 @@ namespace nasal
|
||||
if( !ghost_type )
|
||||
return naNil();
|
||||
|
||||
return naNewGhost2(c, ghost_type, new RefType(ref_ptr));
|
||||
return naNewGhost2( c,
|
||||
ghost_type,
|
||||
shared_ptr_storage<RefType>::ref(ref_ptr) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -801,14 +833,8 @@ namespace nasal
|
||||
* Nasal objects has to be derived class of the target class (Either
|
||||
* derived in C++ or in Nasal using a 'parents' vector)
|
||||
*/
|
||||
template<class RefType>
|
||||
static
|
||||
typename boost::enable_if_c<
|
||||
boost::is_same<RefType, strong_ref>::value
|
||||
|| boost::is_same<RefType, weak_ref>::value,
|
||||
RefType
|
||||
>::type
|
||||
fromNasal(naContext c, naRef me)
|
||||
template<class Type>
|
||||
static Type fromNasal(naContext c, naRef me)
|
||||
{
|
||||
bool is_weak = false;
|
||||
|
||||
@ -816,8 +842,8 @@ namespace nasal
|
||||
if( isBaseOf(naGhost_type(me), is_weak) )
|
||||
{
|
||||
void* ghost = naGhost_ptr(me);
|
||||
return is_weak ? getPtr<RefType, true>(ghost)
|
||||
: getPtr<RefType, false>(ghost);
|
||||
return is_weak ? getPtr<Type, true>(ghost)
|
||||
: getPtr<Type, false>(ghost);
|
||||
}
|
||||
|
||||
// Now if it is derived from a ghost (hash with ghost in parent vector)
|
||||
@ -825,7 +851,7 @@ namespace nasal
|
||||
{
|
||||
naRef na_parents = naHash_cget(me, const_cast<char*>("parents"));
|
||||
if( !naIsVector(na_parents) )
|
||||
return RefType();
|
||||
return Type();
|
||||
|
||||
typedef std::vector<naRef> naRefs;
|
||||
naRefs parents = from_nasal<naRefs>(c, na_parents);
|
||||
@ -833,13 +859,13 @@ namespace nasal
|
||||
parent != parents.end();
|
||||
++parent )
|
||||
{
|
||||
RefType ptr = fromNasal<RefType>(c, *parent);
|
||||
Type ptr = fromNasal<Type>(c, *parent);
|
||||
if( get_pointer(ptr) )
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return RefType();
|
||||
return Type();
|
||||
}
|
||||
|
||||
static bool isBaseOf(naRef obj)
|
||||
@ -881,8 +907,11 @@ namespace nasal
|
||||
>::type
|
||||
getPtr(void* ptr)
|
||||
{
|
||||
typedef shared_ptr_storage<strong_ref> storage_type;
|
||||
if( ptr )
|
||||
return RefPtr(*static_cast<strong_ref*>(ptr));
|
||||
return storage_type::template get<RefPtr>(
|
||||
static_cast<typename storage_type::storage_type*>(ptr)
|
||||
);
|
||||
else
|
||||
return RefPtr();
|
||||
}
|
||||
@ -895,8 +924,11 @@ namespace nasal
|
||||
>::type
|
||||
getPtr(void* ptr)
|
||||
{
|
||||
typedef shared_ptr_storage<weak_ref> storage_type;
|
||||
if( ptr )
|
||||
return RefPtr(*static_cast<weak_ref*>(ptr));
|
||||
return storage_type::template get<RefPtr>(
|
||||
static_cast<typename storage_type::storage_type*>(ptr)
|
||||
);
|
||||
else
|
||||
return RefPtr();
|
||||
}
|
||||
@ -990,25 +1022,6 @@ namespace nasal
|
||||
return getSingletonHolder().get();
|
||||
}
|
||||
|
||||
static raw_type& requireObject(naContext c, naRef me)
|
||||
{
|
||||
raw_type* obj = get_pointer( fromNasal<strong_ref>(c, me) );
|
||||
|
||||
if( !obj )
|
||||
{
|
||||
naGhostType* ghost_type = naGhost_type(me);
|
||||
naRuntimeError
|
||||
(
|
||||
c,
|
||||
"method called on object of wrong type: is '%s' expected '%s'",
|
||||
naIsNil(me) ? "nil" : (ghost_type ? ghost_type->name : "unknown"),
|
||||
_ghost_type_strong.name
|
||||
);
|
||||
}
|
||||
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template<class Ret>
|
||||
getter_t to_getter(Ret (raw_type::*getter)() const)
|
||||
{
|
||||
@ -1138,10 +1151,8 @@ namespace nasal
|
||||
_ghost_type_strong.destroy =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, queueDestroy<strong_ref>);
|
||||
_ghost_type_strong.name = _name_strong.c_str();
|
||||
_ghost_type_strong.get_member =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, getMember<false>);
|
||||
_ghost_type_strong.set_member =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, setMember<false>);
|
||||
_ghost_type_strong.get_member = &Ghost::getMemberStrong;
|
||||
_ghost_type_strong.set_member = &Ghost::setMemberStrong;
|
||||
|
||||
_ghost_type_weak.destroy =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, queueDestroy<weak_ref>);
|
||||
@ -1149,10 +1160,8 @@ namespace nasal
|
||||
|
||||
if( supports_weak_ref<T>::value )
|
||||
{
|
||||
_ghost_type_weak.get_member =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, getMember<true>);
|
||||
_ghost_type_weak.set_member =
|
||||
SG_GET_TEMPLATE_MEMBER(Ghost, setMember<true>);
|
||||
_ghost_type_weak.get_member = &Ghost::getMemberWeak;
|
||||
_ghost_type_weak.set_member = &Ghost::setMemberWeak;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1170,7 +1179,10 @@ namespace nasal
|
||||
template<class Type>
|
||||
static void destroy(void *ptr)
|
||||
{
|
||||
delete static_cast<Type*>(ptr);
|
||||
typedef shared_ptr_storage<Type> storage_type;
|
||||
storage_type::unref(
|
||||
static_cast<typename storage_type::storage_type*>(ptr)
|
||||
);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
@ -1179,6 +1191,17 @@ namespace nasal
|
||||
_destroy_list.push_back( DestroyList::value_type(&destroy<Type>, ptr) );
|
||||
}
|
||||
|
||||
static void raiseErrorExpired(naContext c, const char* str)
|
||||
{
|
||||
Ghost* ghost_info = getSingletonPtr();
|
||||
naRuntimeError(
|
||||
c,
|
||||
"Ghost::%s: ghost has expired '%s'",
|
||||
str,
|
||||
ghost_info ? ghost_info->_name_strong.c_str() : "unknown"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for retrieving a ghost member.
|
||||
*/
|
||||
@ -1218,14 +1241,25 @@ namespace nasal
|
||||
return "";
|
||||
}
|
||||
|
||||
template<bool is_weak>
|
||||
static const char* getMember( naContext c,
|
||||
void* ghost,
|
||||
naRef key,
|
||||
naRef* out )
|
||||
static const char*
|
||||
getMemberWeak(naContext c, void* ghost, naRef key, naRef* out)
|
||||
{
|
||||
strong_ref const& ptr = getPtr<strong_ref, is_weak>(ghost);
|
||||
return getMemberImpl(c, *get_pointer(ptr), key, out);
|
||||
// Keep a strong reference while retrieving member, to prevent deleting
|
||||
// object in between.
|
||||
strong_ref ref = getPtr<strong_ref, true>(ghost);
|
||||
if( !ref )
|
||||
raiseErrorExpired(c, "getMember");
|
||||
|
||||
return getMemberImpl(c, *get_pointer(ref), key, out);
|
||||
}
|
||||
|
||||
static const char*
|
||||
getMemberStrong(naContext c, void* ghost, naRef key, naRef* out)
|
||||
{
|
||||
// Just get a raw pointer as we are keeping a strong reference as ghost
|
||||
// anyhow.
|
||||
raw_type* ptr = getPtr<raw_type*, false>(ghost);
|
||||
return getMemberImpl(c, *ptr, key, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1256,14 +1290,25 @@ namespace nasal
|
||||
member->second.setter(obj, c, val);
|
||||
}
|
||||
|
||||
template<bool is_weak>
|
||||
static void setMember( naContext c,
|
||||
void* ghost,
|
||||
naRef field,
|
||||
naRef val )
|
||||
static void
|
||||
setMemberWeak(naContext c, void* ghost, naRef field, naRef val)
|
||||
{
|
||||
strong_ref const& ptr = getPtr<strong_ref, is_weak>(ghost);
|
||||
return setMemberImpl(c, *get_pointer(ptr), field, val);
|
||||
// Keep a strong reference while retrieving member, to prevent deleting
|
||||
// object in between.
|
||||
strong_ref ref = getPtr<strong_ref, true>(ghost);
|
||||
if( !ref )
|
||||
raiseErrorExpired(c, "setMember");
|
||||
|
||||
setMemberImpl(c, *get_pointer(ref), field, val);
|
||||
}
|
||||
|
||||
static void
|
||||
setMemberStrong(naContext c, void* ghost, naRef field, naRef val)
|
||||
{
|
||||
// Just get a raw pointer as we are keeping a strong reference as ghost
|
||||
// anyhow.
|
||||
raw_type* ptr = getPtr<raw_type*, false>(ghost);
|
||||
setMemberImpl(c, *ptr, field, val);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1313,7 +1358,7 @@ from_nasal_helper(naContext c, naRef ref, const T*)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any pointer to a SGReference based object to a ghost.
|
||||
* Convert any pointer to a SGReferenced based object to a ghost.
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if_c<
|
||||
@ -1327,7 +1372,7 @@ to_nasal_helper(naContext c, T* ptr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nasal ghosts/hashes to pointer (of a SGReference based ghost).
|
||||
* Convert nasal ghosts/hashes to pointer (of a SGReferenced based ghost).
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if_c<
|
||||
@ -1344,7 +1389,34 @@ typename boost::enable_if_c<
|
||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||
{
|
||||
typedef SGSharedPtr<typename boost::remove_pointer<T>::type> TypeRef;
|
||||
return nasal::Ghost<TypeRef>::template fromNasal<TypeRef>(c, ref).release();
|
||||
return nasal::Ghost<TypeRef>::template fromNasal<T>(c, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any pointer to a osg::Referenced based object to a ghost.
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if<
|
||||
boost::is_base_of<osg::Referenced, T>,
|
||||
naRef
|
||||
>::type
|
||||
to_nasal_helper(naContext c, T* ptr)
|
||||
{
|
||||
return nasal::Ghost<osg::ref_ptr<T> >::makeGhost(c, osg::ref_ptr<T>(ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nasal ghosts/hashes to pointer (of a osg::Referenced based ghost).
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if<
|
||||
boost::is_base_of<osg::Referenced, typename boost::remove_pointer<T>::type>,
|
||||
T
|
||||
>::type
|
||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||
{
|
||||
typedef osg::ref_ptr<typename boost::remove_pointer<T>::type> TypeRef;
|
||||
return nasal::Ghost<TypeRef>::template fromNasal<T>(c, ref);
|
||||
}
|
||||
|
||||
#endif /* SG_NASAL_GHOST_HXX_ */
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <BoostTestTargetConfig.h>
|
||||
|
||||
#include "Ghost.hxx"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
class Base1:
|
||||
public virtual SGVirtualWeakReferenced
|
||||
@ -36,6 +38,7 @@ typedef SGSharedPtr<SGReferenced> SGReferencedPtr;
|
||||
CHECK_PTR_TRAIT_TYPE(weak, weak_ref, weak)\
|
||||
|
||||
CHECK_PTR_TRAIT(DerivedPtr, DerivedWeakPtr)
|
||||
CHECK_PTR_TRAIT(boost::shared_ptr<Base1>, boost::weak_ptr<Base1>)
|
||||
|
||||
#undef CHECK_PTR_TRAIT
|
||||
#undef CHECK_PTR_TRAIT_TYPE
|
||||
@ -87,3 +90,52 @@ BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion )
|
||||
|
||||
BOOST_REQUIRE( !weak.lock() );
|
||||
}
|
||||
|
||||
#define CHECK_PTR_STORAGE_TRAIT_TYPE(ptr_t, storage)\
|
||||
BOOST_STATIC_ASSERT((boost::is_same<\
|
||||
nasal::shared_ptr_storage<ptr_t>::storage_type,\
|
||||
storage\
|
||||
>::value));
|
||||
|
||||
CHECK_PTR_STORAGE_TRAIT_TYPE(DerivedPtr, Derived)
|
||||
CHECK_PTR_STORAGE_TRAIT_TYPE(DerivedWeakPtr, DerivedWeakPtr)
|
||||
|
||||
typedef boost::shared_ptr<Derived> BoostDerivedPtr;
|
||||
CHECK_PTR_STORAGE_TRAIT_TYPE(BoostDerivedPtr, BoostDerivedPtr)
|
||||
|
||||
typedef boost::weak_ptr<Derived> BoostDerivedWeakPtr;
|
||||
CHECK_PTR_STORAGE_TRAIT_TYPE(BoostDerivedWeakPtr, BoostDerivedWeakPtr)
|
||||
|
||||
#undef CHECK_PTR_STORAGE_TRAIT_TYPE
|
||||
|
||||
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<Base1Ptr>::is_intrusive::value));
|
||||
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<Base2Ptr>::is_intrusive::value));
|
||||
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<DerivedPtr>::is_intrusive::value));
|
||||
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<DerivedWeakPtr>::is_intrusive::value));
|
||||
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<SGReferencedPtr>::is_intrusive::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((!nasal::shared_ptr_traits<boost::shared_ptr<Derived> >::is_intrusive::value));
|
||||
BOOST_STATIC_ASSERT((!nasal::shared_ptr_traits<boost::weak_ptr<Derived> >::is_intrusive::value));
|
||||
|
||||
BOOST_AUTO_TEST_CASE( storage_traits )
|
||||
{
|
||||
DerivedPtr d = new Derived();
|
||||
|
||||
Derived* d_raw = nasal::shared_ptr_storage<DerivedPtr>::ref(d);
|
||||
BOOST_REQUIRE_EQUAL(d_raw, d.get());
|
||||
BOOST_REQUIRE_EQUAL(d.getNumRefs(), 2);
|
||||
|
||||
DerivedWeakPtr* d_weak = nasal::shared_ptr_storage<DerivedWeakPtr>::ref(d);
|
||||
BOOST_REQUIRE_EQUAL(
|
||||
nasal::shared_ptr_storage<DerivedWeakPtr>::get<Derived*>(d_weak),
|
||||
d_raw
|
||||
);
|
||||
|
||||
d.reset();
|
||||
BOOST_REQUIRE_EQUAL(Derived::count(d_raw), 1);
|
||||
|
||||
nasal::shared_ptr_storage<DerivedPtr>::unref(d_raw);
|
||||
BOOST_REQUIRE(d_weak->expired());
|
||||
|
||||
nasal::shared_ptr_storage<DerivedWeakPtr>::unref(d_weak);
|
||||
}
|
||||
|
@ -22,8 +22,10 @@
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
// Forward declarations
|
||||
class SGReferenced;
|
||||
class SGWeakReferenced;
|
||||
template<class T> class SGSharedPtr;
|
||||
template<class T> class SGWeakPtr;
|
||||
@ -36,6 +38,7 @@ namespace boost
|
||||
}
|
||||
namespace osg
|
||||
{
|
||||
class Referenced;
|
||||
template<class T> class ref_ptr;
|
||||
template<class T> class observer_ptr;
|
||||
|
||||
@ -77,25 +80,27 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
|
||||
public boost::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
#define SG_MAKE_SHARED_PTR_TRAIT(ref, weak)\
|
||||
#define SG_MAKE_SHARED_PTR_TRAIT(strong, weak, intrusive)\
|
||||
template<class T>\
|
||||
struct shared_ptr_traits<ref<T> >\
|
||||
struct shared_ptr_traits<strong<T> >\
|
||||
{\
|
||||
typedef ref<T> strong_ref;\
|
||||
typedef weak<T> weak_ref;\
|
||||
typedef T element_type;\
|
||||
typedef strong<T> strong_ref;\
|
||||
typedef weak<T> weak_ref;\
|
||||
typedef T element_type;\
|
||||
typedef boost::integral_constant<bool, true> is_strong;\
|
||||
typedef boost::integral_constant<bool, intrusive> is_intrusive;\
|
||||
};\
|
||||
template<class T>\
|
||||
struct shared_ptr_traits<weak<T> >\
|
||||
{\
|
||||
typedef ref<T> strong_ref;\
|
||||
typedef weak<T> weak_ref;\
|
||||
typedef T element_type;\
|
||||
typedef strong<T> strong_ref;\
|
||||
typedef weak<T> weak_ref;\
|
||||
typedef T element_type;\
|
||||
typedef boost::integral_constant<bool, false> is_strong;\
|
||||
typedef boost::integral_constant<bool, intrusive> is_intrusive;\
|
||||
};\
|
||||
template<class T>\
|
||||
struct is_strong_ref<ref<T> >:\
|
||||
struct is_strong_ref<strong<T> >:\
|
||||
public boost::integral_constant<bool, true>\
|
||||
{};\
|
||||
template<class T>\
|
||||
@ -103,9 +108,9 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
|
||||
public boost::integral_constant<bool, true>\
|
||||
{};
|
||||
|
||||
SG_MAKE_SHARED_PTR_TRAIT(SGSharedPtr, SGWeakPtr)
|
||||
SG_MAKE_SHARED_PTR_TRAIT(osg::ref_ptr, osg::observer_ptr)
|
||||
SG_MAKE_SHARED_PTR_TRAIT(boost::shared_ptr, boost::weak_ptr)
|
||||
SG_MAKE_SHARED_PTR_TRAIT(SGSharedPtr, SGWeakPtr, true)
|
||||
SG_MAKE_SHARED_PTR_TRAIT(osg::ref_ptr, osg::observer_ptr, true)
|
||||
SG_MAKE_SHARED_PTR_TRAIT(boost::shared_ptr, boost::weak_ptr, false)
|
||||
|
||||
#undef SG_MAKE_SHARED_PTR_TRAIT
|
||||
|
||||
@ -122,5 +127,140 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
|
||||
>
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct shared_ptr_storage
|
||||
{
|
||||
typedef T storage_type;
|
||||
typedef typename T::element_type element_type;
|
||||
typedef typename shared_ptr_traits<T>::strong_ref strong_ref;
|
||||
typedef typename shared_ptr_traits<T>::weak_ref weak_ref;
|
||||
|
||||
template<class U>
|
||||
static storage_type* ref(U ptr)
|
||||
{
|
||||
return new storage_type(ptr);
|
||||
}
|
||||
static void unref(storage_type* ptr)
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if<
|
||||
boost::is_same<U, element_type*>,
|
||||
element_type*
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return get_pointer(*ptr);
|
||||
}
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if_c<
|
||||
boost::is_same<U, strong_ref>::value
|
||||
|| (boost::is_same<U, weak_ref>::value && supports_weak_ref<U>::value),
|
||||
U
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return U(*ptr);
|
||||
}
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if_c<
|
||||
boost::is_same<U, weak_ref>::value
|
||||
&& !supports_weak_ref<U>::value,
|
||||
U
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return U();
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template<class T>
|
||||
struct intrusive_ptr_storage
|
||||
{
|
||||
typedef typename T::element_type storage_type;
|
||||
typedef typename T::element_type element_type;
|
||||
typedef typename shared_ptr_traits<T>::strong_ref strong_ref;
|
||||
typedef typename shared_ptr_traits<T>::weak_ref weak_ref;
|
||||
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if<
|
||||
boost::is_same<U, element_type*>,
|
||||
element_type*
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if_c<
|
||||
boost::is_same<U, strong_ref>::value
|
||||
|| (boost::is_same<U, weak_ref>::value && supports_weak_ref<U>::value),
|
||||
U
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return U(ptr);
|
||||
}
|
||||
template<class U>
|
||||
static
|
||||
typename boost::enable_if_c<
|
||||
boost::is_same<U, weak_ref>::value
|
||||
&& !supports_weak_ref<U>::value,
|
||||
U
|
||||
>::type
|
||||
get(storage_type* ptr)
|
||||
{
|
||||
return U();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct shared_ptr_storage<SGSharedPtr<T> >:
|
||||
public internal::intrusive_ptr_storage<SGSharedPtr<T> >
|
||||
{
|
||||
typedef T storage_type;
|
||||
typedef T element_type;
|
||||
|
||||
static storage_type* ref(element_type* ptr)
|
||||
{
|
||||
T::get(ptr);
|
||||
return ptr;
|
||||
}
|
||||
static void unref(storage_type* ptr)
|
||||
{
|
||||
if( !T::put(ptr) )
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct shared_ptr_storage<osg::ref_ptr<T> >:
|
||||
public internal::intrusive_ptr_storage<osg::ref_ptr<T> >
|
||||
{
|
||||
typedef T storage_type;
|
||||
typedef T element_type;
|
||||
|
||||
|
||||
static storage_type* ref(element_type* ptr)
|
||||
{
|
||||
ptr->ref();
|
||||
return ptr;
|
||||
}
|
||||
static void unref(storage_type* ptr)
|
||||
{
|
||||
ptr->unref();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nasal
|
||||
#endif /* SG_NASAL_TRAITS_HXX_ */
|
||||
|
Loading…
Reference in New Issue
Block a user