#include "NasalObjectHolder.hxx"
#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+#include <simgear/structure/SGWeakPtr.hxx>
#include <boost/bind.hpp>
#include <boost/call_traits.hpp>
/**
* Hold callable method and convert to Nasal function if required.
*/
- class MethodHolder
+ class MethodHolder:
+ public SGWeakReferenced
{
public:
virtual ~MethodHolder() {}
naRef get_naRef(naContext c)
{
- if( !_obj )
- _obj = ObjectHolder::makeShared(createNasalObject(c));
- return _obj->get_naRef();
+ if( !_obj.valid() )
+ _obj.reset(createNasalObject(c));
+ return _obj.get_naRef();
}
protected:
- ObjectHolderRef _obj;
+ ObjectHolder _obj;
virtual naRef createNasalObject(naContext c) = 0;
};
{};
}
+ typedef SGSharedPtr<internal::MethodHolder> MethodHolderPtr;
+ typedef SGWeakPtr<internal::MethodHolder> MethodHolderWeakPtr;
+
/**
* Class for exposing C++ objects to Nasal
*
typedef boost::function<naRef(naContext, raw_type&)> getter_t;
typedef boost::function<void(naContext, raw_type&, naRef)> setter_t;
typedef boost::function<naRef(raw_type&, const CallContext&)> method_t;
- typedef boost::shared_ptr<internal::MethodHolder> MethodHolderPtr;
class MethodHolder:
public internal::MethodHolder
{}
protected:
+
+ typedef SGSharedPtr<MethodHolder> SharedPtr;
+ typedef SGWeakPtr<MethodHolder> WeakPtr;
+
method_t _method;
virtual naRef createNasalObject(naContext c)
{
- return naNewFunc(c, naNewCCodeU(c, &MethodHolder::call, this));
+ return naNewFunc
+ (
+ c,
+ naNewCCodeUD( c,
+ &MethodHolder::call,
+ new WeakPtr(this),
+ &destroyHolder )
+ );
+ }
+
+ static void destroyHolder(void* user_data)
+ {
+ delete static_cast<WeakPtr*>(user_data);
}
static naRef call( naContext c,
naRef* args,
void* user_data )
{
- MethodHolder* holder = static_cast<MethodHolder*>(user_data);
- if( !holder )
+ WeakPtr* holder_weak = static_cast<WeakPtr*>(user_data);
+ if( !holder_weak )
naRuntimeError(c, "invalid method holder!");
try
{
+ SharedPtr holder = holder_weak->lock();
+ if( !holder )
+ throw std::runtime_error("holder has expired");
+
return holder->_method
(
requireObject(c, me),
*/
Ghost& method(const std::string& name, const method_t& func)
{
- _members[name].func.reset( new MethodHolder(func) );
+ _members[name].func = new MethodHolder(func);
return *this;
}
//----------------------------------------------------------------------------
ObjectHolder::~ObjectHolder()
{
- naGCRelease(_gc_key);
+ if( !naIsNil(_ref) )
+ naGCRelease(_gc_key);
}
//----------------------------------------------------------------------------
return _ref;
}
+ //----------------------------------------------------------------------------
+ void ObjectHolder::reset()
+ {
+ if( !naIsNil(_ref) )
+ naGCRelease(_gc_key);
+
+ _ref = naNil();
+ _gc_key = 0;
+ }
+
+ //----------------------------------------------------------------------------
+ void ObjectHolder::reset(naRef obj)
+ {
+ if( !naIsNil(_ref) )
+ naGCRelease(_gc_key);
+
+ _ref = obj;
+ _gc_key = naGCSave(obj);
+ }
+
+ //----------------------------------------------------------------------------
+ bool ObjectHolder::valid() const
+ {
+ return !naIsNil(_ref);
+ }
+
//----------------------------------------------------------------------------
ObjectHolderRef ObjectHolder::makeShared(naRef obj)
{
//----------------------------------------------------------------------------
ObjectHolder::ObjectHolder(naRef obj):
_ref(obj),
- _gc_key(naGCSave(obj))
+ _gc_key(0)
+ {
+ if( !naIsNil(obj) )
+ naGCSave(obj);
+ }
+
+ //----------------------------------------------------------------------------
+ ObjectHolder::ObjectHolder():
+ _ref(naNil()),
+ _gc_key(0)
{
}
{
public:
+ /**
+ * @param obj Object to save
+ */
+ explicit ObjectHolder(naRef obj);
+
+ /**
+ *
+ */
+ ObjectHolder();
+
/**
*
*/
*/
naRef get_naRef() const;
+ /**
+ * Release the managed object
+ */
+ void reset();
+
+ /**
+ * Replaces the managed object (the old object is released)
+ *
+ * @param obj New object to save
+ */
+ void reset(naRef obj);
+
+ /**
+ * Check if there is a managed object
+ */
+ bool valid() const;
+
/**
* Save the given object as long as the returned holder exists.
*
protected:
naRef _ref;
int _gc_key;
-
- /**
- * @param obj Object to save
- */
- ObjectHolder(naRef obj);
};
} // namespace nasal