lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello list
I am back to lua, reworking luapi to ´true´ 5.0 final, and testing
extensively the suspicious points,
which are what could derive from the two functions I added to lapi.c ...
code follows
////////////////////////
/*
   extended api functions for lua 5.0
   use with care
*/


#include <luaex.h>

// This is the most important function for the luapi library. It allows most
routines to completely clear
// the stack before return. The lua objects in the stack are stored in host
data structures, which
// may be pushed again later. When the objects are the simple ones, the
usual apis are enough, but
// when dealing with the complex ones, there is no official api, so I
devised this one, which seems
// correct. I would like the word from the lua authors.
// Simply, when dealing with these 3 types, the host program stores the
pointer ( lua_topointer )
// and the type, then when it comes to push again some object, it calls this
function.
// Essentially, it uses the same macros that the _new.... apis do.
// Of course, the correlation between the type and the pointer is warranted.
void lua_pushobject( lua_State * L, void * ptr, int objtype ) {

   Udata * u;

   switch( objtype ) {
      case LUA_TTABLE    :
           sethvalue( L->top, (Table *) ptr);
           break;
      case LUA_TFUNCTION :
           setclvalue( L->top, ptr );
           break;
      case LUA_TUSERDATA :
           u           = (Udata *) ptr;
           u          -= 1;
           setuvalue( L->top, u );
           break;
      default            :
           lua_pushliteral( L, "pushobject: improper type\n" );
           lua_error( L );
           break;
   }
// The strange operation with the userdata pointer is the complement of what
lua_topointer does.
   api_incr_top( L );
}

// this is a simple cast from a constant pointer to a non constant one
void * lua_toobject( lua_State * L, int index )
{
   const void * r = lua_topointer( L, index );
   return (void *) r;
}
///////////////////
All the stuff seems to work ... exceptions are some lua scripts when
iterated many times in the same
lua context. I devised a simple method to execute n times a given script, so
forcing the gc lots of
times, and ( I think ) testing near all the lua and luapi code.
But some strange results are scaring me. Some background: to test my
userdata support functions
and policy, I have a ´library´ which registers a userdata which essentially
points to some C structure.
The trick is that the library allows both temporary and static userdata. The
difference is simple:
when allocating the userdata for a static host object, only a pointer is
requested, and made to point
to some of the static instances. These userdata are registered in lua as
globals, so they never becomes
GC´ed. On the other way, whenever a local temporary ( in lua ) is required,
the size requested to lua
is increased by the size of the structure itself and for the ´C´ object
which the structure points to.
So, the __gc metamethod is a curiosity: no resources must be released in the
host data space.
The ´C´ object is a wrapper ( like a variant ) around the basic C objects:
ints, doubles and char strings. As such, some events must be implemented:
__add, __sub, etc
The library exports 6 global userdata, one of which, called Dbl1 is used as
a base for the examples
Two lua scripts exploiting this userdata follows:
Script # 1
-- GC test for user data . based on ud3.lua, less verbose

-- try a variation : wrap the thing in do end - don´t help

do

local a =  20 + Dbl1 - 10
a = a + 5

local b =  30 + Dbl1 - 15
b = b + 10

local c =  40 + Dbl1 - 20
c = c + 15

function show( )
   print( "a", a:Tohr( ) )
end

end

Script # 2
-- GC test for user data . based on ud3.lua, less verbose

function doud( )
   local a = Dbl1 + 10;
   local b = Dbl1 + 20;
   local c = Dbl1 + 30;
   print( a:Tohr( ), b:Tohr( ), c:Tohr( ) )
end

Tohr is a method like __tostring, nothing fancy.
Using the repeater feature, the script # 2 can be loaded and the function
doud executed 10000
times, without worry. Of course, the __gc metamethod is called lots of times
!!!
But the script # 1 can be iterated ( loading and calling show( ) ) only 24
times, anything more yields a SIGSEGV. Of course, both scripts requires
minimal amounts of memory ( some 140 kb ).
I am very worry, because I cannot discern why the  first script fails to
execute an undefined number
of iterations. Even running 15 iterations, the gc is called lot of times !!!
Oh, I must to say that the return value from any arith methods is a fully
allocated userdata of the same
type !!
What is wrong ? Am I missing something ?