Lua struct obj improvements

If the core frees the obj struct referred by lua, don't free it,
just mark it as OBJ_LUAFREE - lua will free it in gc once all
the references to it are gone.
This commit is contained in:
Pasi Kallinen
2020-01-01 13:25:55 +02:00
parent 2ae7cf02ea
commit 7e07cef197
5 changed files with 58 additions and 30 deletions

View File

@@ -1969,6 +1969,7 @@ struct monst *mtmp;
* OBJ_MIGRATING migrating chain
* OBJ_BURIED level.buriedobjs chain
* OBJ_ONBILL on g.billobjs chain
* OBJ_LUAFREE obj is dealloc'd from core, but still used by lua
*/
void
obj_extract_self(obj)
@@ -1976,6 +1977,7 @@ struct obj *obj;
{
switch (obj->where) {
case OBJ_FREE:
case OBJ_LUAFREE:
break;
case OBJ_FLOOR:
remove_object(obj);
@@ -2161,7 +2163,7 @@ void
dealloc_obj(obj)
struct obj *obj;
{
if (obj->where != OBJ_FREE)
if (obj->where != OBJ_FREE && obj->where != OBJ_LUAFREE)
panic("dealloc_obj: obj not free");
if (obj->nobj)
panic("dealloc_obj with nobj");
@@ -2192,8 +2194,11 @@ struct obj *obj;
if (obj->oextra)
dealloc_oextra(obj);
if (obj->lua_ref_cnt)
return; /* obj is referenced from a lua script, let lua gc free it */
if (obj->lua_ref_cnt) {
/* obj is referenced from a lua script, let lua gc free it */
obj->where = OBJ_LUAFREE;
return;
}
free((genericptr_t) obj);
}
@@ -2430,7 +2435,8 @@ const char *mesg;
static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
"contained", "invent",
"minvent", "migrating",
"buried", "onbill" };
"buried", "onbill",
"luafree" };
static const char *
where_name(obj)

View File

@@ -22,6 +22,8 @@ struct _lua_obj {
struct obj *obj;
};
#define lobj_is_ok(lo) ((lo) && (lo)->obj && (lo)->obj->where != OBJ_LUAFREE)
struct _lua_obj *
l_obj_check(L, index)
lua_State *L;
@@ -46,7 +48,8 @@ lua_State *L;
if (lo->obj->lua_ref_cnt > 0)
lo->obj->lua_ref_cnt--;
/* free-floating objects with no other refs are deallocated. */
if (lo->obj->where == OBJ_FREE && !lo->obj->lua_ref_cnt) {
if (!lo->obj->lua_ref_cnt
&& (lo->obj->where == OBJ_FREE || lo->obj->where == OBJ_LUAFREE)) {
if (Has_contents(lo->obj)) {
struct obj *otmp;
while ((otmp = lo->obj->cobj) != 0) {
@@ -98,13 +101,12 @@ lua_State *L;
if (!obj)
nhl_error(L, "l_obj_getcontents: no obj");
if (!obj->cobj)
nhl_error(L, "l_obj_getcontents: no cobj");
(void) l_obj_push(L, obj->cobj);
return 1;
}
/* Puts object inside another object. */
/* local box = obj.new("large chest");
box.addcontent(obj.new("rock"));
*/
@@ -115,19 +117,21 @@ lua_State *L;
struct _lua_obj *lobox = l_obj_check(L, 1);
struct _lua_obj *lo = l_obj_check(L, 2);
struct obj *otmp;
int refs;
if (!lo->obj || !lobox->obj)
nhl_error(L, "l_obj_add_to_container: no obj");
if (!lobj_is_ok(lo) || !lobj_is_ok(lobox))
return 0;
if (!Is_container(lobox->obj))
nhl_error(L, "l_obj_add_to_container: not a container");
refs = lo->obj->lua_ref_cnt;
obj_extract_self(lo->obj);
otmp = add_to_container(lobox->obj, lo->obj);
/* was lo->obj merged? FIXME: causes problems if both lo->obj and
the one it merged with are handled by lua. Use lo->state? */
if (otmp != lo->obj)
/* was lo->obj merged? */
if (otmp != lo->obj) {
lo->obj->lua_ref_cnt += refs;
lo->obj = otmp;
}
return 0;
}
@@ -135,6 +139,7 @@ lua_State *L;
/* Get a table of object class data. */
/* local odata = obj.class(otbl.otyp); */
/* local odata = obj.class(obj.new("rock")); */
/* local odata = o:class(); */
static int
l_obj_objects_to_table(L)
lua_State *L;
@@ -217,7 +222,7 @@ lua_State *L;
lua_newtable(L);
if (!obj) {
if (!obj || obj->where == OBJ_LUAFREE) {
nhl_add_table_entry_int(L, "NO_OBJ", 1);
return 1;
}
@@ -352,20 +357,19 @@ lua_State *L;
{
int argc = lua_gettop(L);
struct _lua_obj *lo = l_obj_check(L, 1);
int x, y;
if (argc != 3)
nhl_error(L, "l_obj_placeobj: Wrong args");
if (lo && lo->obj) {
int x, y;
x = (int) luaL_checkinteger(L, 2);
y = (int) luaL_checkinteger(L, 3);
lua_pop(L, 3);
x = (int) luaL_checkinteger(L, 2);
y = (int) luaL_checkinteger(L, 3);
lua_pop(L, 3);
if (lobj_is_ok(lo)) {
obj_extract_self(lo->obj);
place_object(lo->obj, x, y);
} else
nhl_error(L, "l_obj_placeobj: Wrong args");
}
return 0;
}
@@ -393,11 +397,10 @@ lua_State *L;
{
struct _lua_obj *lo = l_obj_check(L, 1);
if (lo && lo->obj && lo->obj->where == OBJ_CONTAINED) {
if (lo && lo->obj && lo->obj->where == OBJ_CONTAINED)
(void) l_obj_push(L, lo->obj->ocontainer);
return 1;
}
(void) l_obj_push(L, NULL);
else
(void) l_obj_push(L, NULL);
return 1;
}
@@ -409,7 +412,7 @@ lua_State *L;
{
struct _lua_obj *lo = l_obj_check(L, 1);
lua_pushboolean(L, lo && lo->obj);
lua_pushboolean(L, lobj_is_ok(lo));
return 1;
}