Closed aster2013 closed 8 years ago
Why don't you use shared_ptr?
state["data"] = std::shared_ptr<RefCounted>(refcounted_ptr,RefCountedGC) ;
it is an existed game engine, it use tolua to binding cpp code to lua, as you know tolua is slow and has memory leak with ref object.
How unique_ptr? example: e0e4009aff982cbf223ef50cf37d62efd34f80fe
What are you doing to care? Performance cost of unique_ptr is less than shared_ptr, and neary equal raw pointer. Them member function invoke cost is nearly equal.
member function invoke performance benchmark results:
data type | seconds | benchmark function name |
---|---|---|
allocated by lua_newuserdata data with plain API | 1.675 | original_api_no_type_check::simple_get_set |
allocated by lua_newuserdata data | 1.554 | kaguya_api_benchmark__::simple_get_set |
raw pointer | 1.729 | kaguya_api_benchmark__::simple_get_set_raw_ptr |
shared_ptr | 1.784 | kaguya_api_benchmark__::simple_get_set_shared_ptr |
unique_ptr | 1.773 | kaguya_api_benchmark__::simple_get_set_unique_ptr |
I am working on the Urho3D game engine, Urho3D/new-luascript-test branch, If you have spare time, please take a look on it.
Wow, interesting work.
Please import e9214b955f1d021c1bc5c5c1fec484f3ecd51eef this fix and specialized for Urho3D::SharedPtr. e.g.
// Urho3D::SharedPtr<T>
template<typename T> struct lua_type_traits<Urho3D::SharedPtr<T> > {
typedef Urho3D::SharedPtr<T>& push_type;
typedef Urho3D::SharedPtr<T>& get_type;
typedef Urho3D::SharedPtr<T> type;
//If need Urho3D::SharedPtr type get.
static bool strictCheckType(lua_State* l, int index)
{
return object_wrapper<type>(l, index, false) != 0;
}
//If need Urho3D::SharedPtr type get.
static bool checkType(lua_State* l, int index)
{
return object_wrapper<type>(l, index) != 0 ||
lua_isnil(l, index);
}
//If need Urho3D::SharedPtr type get.
static get_type get(lua_State* l, int index)
{
type* pointer = get_pointer(l, index, types::typetag<type>());
if (!pointer)
{
throw LuaTypeMismatch("type mismatch!!");
}
return *pointer;
}
static int push(lua_State* l, push_type v)
{
if (v)
{
typedef ObjectSmartPointerWrapper<type,T> wrapper_type;
void *storage = lua_newuserdata(l, sizeof(wrapper_type));
new(storage) wrapper_type(v);
class_userdata::setmetatable<T>(l);
}
else
{
lua_pushnil(l);
}
return 1;
}
};
What I want is like this:
template<typename T>
SharedPtr<T> KCreateObject()
{
SharedPtr<T> tPtr(new T(globalContext));
return tPtr;
}
template<typename T>
void KReleaseObject(T* t)
{
if (t)
t->ReleaseRef();
}
template<typename T> struct lua_type_traits<Urho3D::SharedPtr<T>>
{
typedef const Urho3D::SharedPtr<T>& push_type;
static int push(lua_State* l, push_type p)
{
T* o = p;
o->AddRef();
// Push the raw pointer to Lua
return util::push_args(l, o);
}
};
So current I disable the default gc function in UserdataMetatable constructor, and add custom gc function.
lua["KImage"].setClass(UserdataMetatable<Image, Resource>(false) // don't use defaut gc function
.addStaticFunction("new", &KCreateObject<Image>) // Custom new function
.addStaticFunction("__gc", &KReleaseObject<Image>) // Custom gc function
// ...
Why want? kaguya is wrapped for all user data by ObjectWrapper. That is raw-pointer too. Default gcfunction is call ObjectWrapperBase’s destructor.Your code has not been called.
Thanks, you are right. I have write a shared ptr object wrapper. Please check it
OK!
Sometimes user want to custom __gc function for some userdata, for example: I have a RefCounted object, when GC, it may call following function.
So it is better add a argument to UserdataMetatable enable user custom the gc funciton.