[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Interesting C++ way to allocate user data (placement new)
- From: Francesco Abbate <francesco.bbt@...>
- Date: Wed, 16 May 2012 12:46:09 +0200
2012/5/16 Pablo Pissanetzky <pablo@trickplay.com>:
> Just wanted to share this idea:
>
> void * operator new( size_t size , lua_State * L )
> {
> return lua_newuserdata( L , size );
> }
>
>
> Then:
>
> Foo * foo = new ( L ) Foo( constructor arguments );
I'm using this approach in gsl shell since some time. Actually I use
something like the following:
inline void* operator new(size_t nbytes, lua_State *L, enum gs_type_e tp)
{
void* p = lua_newuserdata(L, nbytes);
gs_set_metatable (L, tp);
return p;
}
template <class T>
T* push_new_object (lua_State *L, enum gs_type_e tp)
{
return new(L, tp) T();
}
template <class T, class init_type>
T* push_new_object (lua_State *L, enum gs_type_e tp, init_type& init)
{
return new(L, tp) T(init);
}
template <class T>
int object_free (lua_State *L, int index, enum gs_type_e tp)
{
T *obj = (T *) gs_check_userdata (L, index, tp);
obj->~T();
return 0;
}
So I have in addition some enums (enum gs_type_e) to tag the type to
retrieve the appropriate metatable. The use of templates is also nice
to have more readable code.
The technique works well for me as far as you pay attention and ensure
that the Lua GC does not free prematurely the memory. The point is
that with the approach above Lua is the owner of the allocated memory
so you have to care about the GC.
The alternative approach is to just allocate a new object with "new"
in the standard way and to hold the pointer in a userdata of
size(void*). While this approach better separate Lua and C++ memory
management it had the disadvantage of introducing more memory
fragmentation and indirection when referencing to the object data with
possible cache misses (?).
Francesco