lua-users home
lua-l archive

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


> The drawback is that everyone using Lua would have to start 
> it with something like
> 
>   lua_open(&realloc);
> 
> which is not exactly friendly... Note that you already can 
> change memory allocation without editing the source:
> 
>   #ifndef l_realloc
>   #define l_realloc(b,os,s)       realloc(b,s)
>   #endif

I offer the following changes I made to Lua 4.1 Alpha which avoids this
problem.  You have to register your callbacks BEFORE lua_open() is
called, although reasonable defaults (Lua's original scheme) are
provided.

Thanks,
Josh

------------------------------------------------------------------

>From lmem.c:

/*
** generic allocation routine.
*/
void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem
size) {
  if (size == 0) {
//    l_free(block, oldsize);  /* block may be NULL; that is OK for free
*/
    (*G(L)->freeFunc)(block, G(L)->memData);
    luaM_setname(L, NULL);
    block = NULL;
  }
  else if (size >= MAX_SIZET)
    luaD_error(L, "memory allocation error: block too big");
  else {
//    block = l_realloc(block, oldsize, size);
    block = (*G(L)->reallocFunc)(block, size, G(L)->memData,
L->allocName, L->allocFlags);
    luaM_setname(L, NULL);
    if (block == NULL) {
      if (L)
        luaD_breakrun(L, LUA_ERRMEM);  /* break run without error
message */
      else return NULL;  /* error before creating state! */
    }
  }
  if (L && G(L)) {
    G(L)->nblocks -= oldsize;
    G(L)->nblocks += size;
  }
  return block;
}

------------------------------------------------------------------------
-------

>From lua.h:

typedef void* (*lua_ReallocFunction)(void* ptr, int size, void* data,
const char* allocName, unsigned int flags);
typedef void (*lua_FreeFunction)(void* ptr, void* data);
void lua_getdefaultmemoryfunctions(lua_ReallocFunction* reallocFunc,
lua_FreeFunction* freeFunc, void** data);
void lua_setdefaultmemoryfunctions(lua_ReallocFunction reallocFunc,
lua_FreeFunction freeFunc, void* data);

------------------------------------------------------------------------
-------

>From lstate.h:

typedef struct global_State {
  lua_ReallocFunction reallocFunc;
  lua_FreeFunction freeFunc;

------------------------------------------------------------------------
-------

>From lstate.c:

static void* luaHelper_ReallocFunction(void* ptr, int size, void* data,
const char* allocName, unsigned int allocFlags)
{
	UNUSED(data);
	UNUSED(allocName);
	UNUSED(allocFlags);
	return realloc(ptr, size);
}


static void luaHelper_FreeFunction(void* ptr, void* data)
{
  UNUSED(data);
  free(ptr);
}


static lua_ReallocFunction luaHelper_Realloc =
luaHelper_ReallocFunction;
static lua_FreeFunction luaHelper_Free = luaHelper_FreeFunction;
static void* luaHelper_memData = NULL;


void lua_getdefaultmemoryfunctions(lua_ReallocFunction* reallocFunc,
lua_FreeFunction* freeFunc, void** data)
{
	*reallocFunc = luaHelper_Realloc;
	*freeFunc = luaHelper_Free;
	*data = luaHelper_memData;
}


void lua_setdefaultmemoryfunctions(lua_ReallocFunction reallocFunc,
lua_FreeFunction freeFunc, void* data)
{
	if (reallocFunc)
		luaHelper_Realloc = reallocFunc;
	else
		luaHelper_Realloc = luaHelper_ReallocFunction;

	if (freeFunc)
		luaHelper_Free = freeFunc;
	else
		luaHelper_Free = luaHelper_FreeFunction;

	luaHelper_memData = data;
}


static void f_luaopen (lua_State *L, void *ud) {
  int i;
  global_State globalState;
  lua_State luaState;
  UNUSED(ud);
  luaState.allocName = "global_State";
  luaState._G = &globalState;
  globalState.reallocFunc = luaHelper_Realloc;
  globalState.freeFunc = luaHelper_Free;
  globalState.memData = luaHelper_memData;
  /* create a new global state */
  L->_G = luaM_new(&luaState, global_State);
  G(L)->reallocFunc = luaHelper_Realloc;
  G(L)->freeFunc = luaHelper_Free;
  G(L)->memData = luaHelper_memData;
  ...
}


LUA_API lua_State *lua_open (void) {
  global_State globalState;
  lua_State luaState;
  lua_State *L;
  luaState.allocName = "global_State";
  luaState._G = &globalState;
  globalState.reallocFunc = luaHelper_Realloc;
  globalState.freeFunc = luaHelper_Free;
  globalState.memData = luaHelper_memData;
  L = luaM_new(&luaState, lua_State);
  ...
}


static void close_state (lua_State *L) {
  global_State globalState;
  lua_State luaState;

  luaF_close(L, L->stack);  /* close all upvalues for this thread */

  luaState._G = &globalState;
  globalState.reallocFunc = G(L)->reallocFunc;
  globalState.freeFunc = G(L)->freeFunc;
  globalState.memData = G(L)->memData;

  if (G(L)) {  /* close global state */
    luaC_collect(L, 1);  /* collect all elements */
    lua_assert(G(L)->rootproto == NULL);
    lua_assert(G(L)->rootudata == NULL);
    lua_assert(G(L)->rootcl == NULL);
    lua_assert(G(L)->rootupval == NULL);
    lua_assert(G(L)->roottable == NULL);
    luaS_freeall(L);
    luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
    luaM_freelem(&luaState, L->_G);
  }
  luaE_closethread(&luaState, L);
}