lock mechanism seperseded by the REFERENCE mechanism.

This commit is contained in:
Roberto Ierusalimschy 1996-04-22 15:00:37 -03:00
parent fed9408ab5
commit 0ef5cf2289
9 changed files with 163 additions and 93 deletions

View File

@ -3,7 +3,7 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_fallback="$Id: fallback.c,v 1.22 1996/03/19 22:28:37 roberto Exp roberto $"; char *rcs_fallback="$Id: fallback.c,v 1.23 1996/03/21 16:31:32 roberto Exp roberto $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -12,6 +12,7 @@ char *rcs_fallback="$Id: fallback.c,v 1.22 1996/03/19 22:28:37 roberto Exp rober
#include "fallback.h" #include "fallback.h"
#include "opcode.h" #include "opcode.h"
#include "lua.h" #include "lua.h"
#include "table.h"
static void errorFB (void); static void errorFB (void);
@ -112,59 +113,74 @@ static void funcFB (void)
/* /*
** Lock routines ** Reference routines
*/ */
static Object *lockArray = NULL; static struct ref {
static int lockSize = 0; Object o;
enum {LOCK, HOLD, FREE, COLLECTED} status;
} *refArray = NULL;
static int refSize = 0;
int luaI_lock (Object *object) lua_Reference luaI_ref (Object *object, int lock)
{ {
int i; int i;
int oldSize; int oldSize;
if (tag(object) == LUA_T_NIL) if (tag(object) == LUA_T_NIL)
return -1; /* special lock ref for nil */ return -1; /* special ref for nil */
for (i=0; i<lockSize; i++) for (i=0; i<refSize; i++)
if (tag(&lockArray[i]) == LUA_T_NIL) if (refArray[i].status == FREE)
{ goto found;
lockArray[i] = *object;
return i;
}
/* no more empty spaces */ /* no more empty spaces */
oldSize = lockSize; oldSize = refSize;
lockSize = growvector(&lockArray, lockSize, Object, lockEM, MAX_WORD); refSize = growvector(&refArray, refSize, struct ref, refEM, MAX_WORD);
for (i=oldSize; i<lockSize; i++) for (i=oldSize; i<refSize; i++)
tag(&lockArray[i]) = LUA_T_NIL; refArray[i].status = FREE;
lockArray[oldSize] = *object; i = oldSize;
return oldSize; found:
refArray[i].o = *object;
refArray[i].status = lock ? LOCK : HOLD;
return i;
} }
void lua_unlock (int ref) void lua_unref (lua_Reference ref)
{ {
if (ref >= 0 && ref < lockSize) if (ref >= 0 && ref < refSize)
tag(&lockArray[ref]) = LUA_T_NIL; refArray[ref].status = FREE;
} }
Object *luaI_getlocked (int ref) Object *luaI_getref (lua_Reference ref)
{ {
static Object nul = {LUA_T_NIL, {0}}; static Object nul = {LUA_T_NIL, {0}};
if (ref >= 0 && ref < lockSize) if (ref == -1)
return &lockArray[ref];
else
return &nul; return &nul;
if (ref >= 0 && ref < refSize &&
(refArray[ref].status == LOCK || refArray[ref].status == HOLD))
return &refArray[ref].o;
else
return NULL;
} }
void luaI_travlock (int (*fn)(Object *)) void luaI_travlock (int (*fn)(Object *))
{ {
int i; int i;
for (i=0; i<lockSize; i++) for (i=0; i<refSize; i++)
fn(&lockArray[i]); if (refArray[i].status == LOCK)
fn(&refArray[i].o);
} }
void luaI_invalidaterefs (void)
{
int i;
for (i=0; i<refSize; i++)
if (refArray[i].status == HOLD && !luaI_ismarked(&refArray[i].o))
refArray[i].status = COLLECTED;
}
char *luaI_travfallbacks (int (*fn)(Object *)) char *luaI_travfallbacks (int (*fn)(Object *))
{ {
int i; int i;

View File

@ -1,10 +1,11 @@
/* /*
** $Id: fallback.h,v 1.10 1995/10/17 11:52:38 roberto Exp roberto $ ** $Id: fallback.h,v 1.11 1996/01/30 15:25:23 roberto Exp roberto $
*/ */
#ifndef fallback_h #ifndef fallback_h
#define fallback_h #define fallback_h
#include "lua.h"
#include "opcode.h" #include "opcode.h"
extern struct FB { extern struct FB {
@ -26,9 +27,10 @@ extern struct FB {
#define FB_GETGLOBAL 9 #define FB_GETGLOBAL 9
void luaI_setfallback (void); void luaI_setfallback (void);
int luaI_lock (Object *object); lua_Reference luaI_ref (Object *object, int lock);
Object *luaI_getlocked (int ref); Object *luaI_getref (lua_Reference ref);
void luaI_travlock (int (*fn)(Object *)); void luaI_travlock (int (*fn)(Object *));
void luaI_invalidaterefs (void);
char *luaI_travfallbacks (int (*fn)(Object *)); char *luaI_travfallbacks (int (*fn)(Object *));
#endif #endif

21
lua.h
View File

@ -2,7 +2,7 @@
** LUA - Linguagem para Usuarios de Aplicacao ** LUA - Linguagem para Usuarios de Aplicacao
** Grupo de Tecnologia em Computacao Grafica ** Grupo de Tecnologia em Computacao Grafica
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: lua.h,v 3.24 1996/03/19 22:28:37 roberto Exp roberto $ ** $Id: lua.h,v 3.25 1996/03/21 21:30:29 roberto Exp roberto $
*/ */
@ -80,17 +80,20 @@ lua_Object lua_getsubscript (void);
int lua_type (lua_Object object); int lua_type (lua_Object object);
int lua_lock (void);
lua_Object lua_getlocked (int ref); typedef int lua_Reference;
void lua_pushlocked (int ref);
void lua_unlock (int ref); lua_Reference lua_ref (int lock);
lua_Object lua_getref (lua_Reference ref);
void lua_pushref (lua_Reference ref);
void lua_unref (lua_Reference ref);
lua_Object lua_createtable (void); lua_Object lua_createtable (void);
/* some useful macros */ /* some useful macros */
#define lua_lockobject(o) (lua_pushobject(o), lua_lock()) #define lua_refobject(o,l) (lua_pushobject(o), lua_ref(l))
#define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n)) #define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n))
@ -99,6 +102,12 @@ lua_Object lua_createtable (void);
/* for compatibility with old versions. Avoid using these macros */ /* for compatibility with old versions. Avoid using these macros */
#define lua_lockobject(o) lua_refobject(o,1)
#define lua_lock() lua_ref(1)
#define lua_getlocked lua_getref
#define lua_pushlocked lua_pushref
#define lua_unlock lua_unref
#define lua_pushliteral(o) lua_pushstring(o) #define lua_pushliteral(o) lua_pushstring(o)
#define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript()) #define lua_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript())

View File

@ -1,7 +1,7 @@
/* /*
** mem.c ** mem.c
** memory manager for lua ** memory manager for lua
** $Id: mem.h,v 1.5 1996/03/21 16:31:32 roberto Exp roberto $ ** $Id: mem.h,v 1.6 1996/03/21 18:54:29 roberto Exp roberto $
*/ */
#ifndef mem_h #ifndef mem_h
@ -18,7 +18,7 @@
#define constantEM "constant table overflow" #define constantEM "constant table overflow"
#define stackEM "stack size overflow" #define stackEM "stack size overflow"
#define lexEM "lex buffer overflow" #define lexEM "lex buffer overflow"
#define lockEM "lock table overflow" #define refEM "reference table overflow"
#define tableEM "table overflow" #define tableEM "table overflow"
#define memEM "not enough memory" #define memEM "not enough memory"

View File

@ -1,4 +1,4 @@
% $Id: manual.tex,v 1.14 1996/03/20 18:44:02 roberto Exp roberto $ % $Id: manual.tex,v 1.15 1996/04/01 14:36:35 roberto Exp roberto $
\documentstyle[fullpage,11pt,bnf]{article} \documentstyle[fullpage,11pt,bnf]{article}
@ -34,7 +34,7 @@ Waldemar Celes Filho
\tecgraf\ --- Departamento de Inform\'atica --- PUC-Rio \tecgraf\ --- Departamento de Inform\'atica --- PUC-Rio
} }
\date{\small \verb$Date: 1996/03/20 18:44:02 $} \date{\small \verb$Date: 1996/04/01 14:36:35 $}
\maketitle \maketitle
@ -739,7 +739,7 @@ The API functions can be classified in the following categories:
\item manipulating (reading and writing) Lua objects; \item manipulating (reading and writing) Lua objects;
\item calling Lua functions; \item calling Lua functions;
\item C functions to be called by Lua; \item C functions to be called by Lua;
\item locking Lua Objects. \item references to Lua Objects.
\end{enumerate} \end{enumerate}
All API functions are declared in the file \verb'lua.h'. All API functions are declared in the file \verb'lua.h'.
@ -1069,30 +1069,39 @@ many results.
Section~\ref{exCFunction} presents an example of a CFunction. Section~\ref{exCFunction} presents an example of a CFunction.
\subsection{Locking Lua Objects} \subsection{References to Lua Objects}
As already noted, \verb'lua_Object's are volatile. As already noted, \verb'lua_Object's are volatile.
If the C code needs to keep a \verb'lua_Object' If the C code needs to keep a \verb'lua_Object'
outside block boundaries, outside block boundaries,
it has to {\em lock} the object. it must create a \Def{reference} to the object.
The routines to manipulate locking are the following: The routines to manipulate references are the following:
\Deffunc{lua_lock}\Deffunc{lua_getlocked} \Deffunc{lua_ref}\Deffunc{lua_getref}
\Deffunc{lua_pushlocked}\Deffunc{lua_unlock} \Deffunc{lua_pushref}\Deffunc{lua_unref}
\begin{verbatim} \begin{verbatim}
int lua_lock (void); typedef int lua_Reference;
lua_Object lua_getlocked (int ref);
void lua_pushlocked (int ref); lua_Reference lua_ref (int lock);
void lua_unlock (int ref); lua_Object lua_getref (lua_Reference ref);
void lua_pushref (lua_Reference ref);
void lua_unref (lua_Reference ref);
\end{verbatim} \end{verbatim}
The function \verb'lua_lock' locks the object The function \verb'lua_ref' creates a reference
which is on the top of the stack, to the object which is on the top of the stack,
and returns a reference to it. and returns this reference.
Whenever the locked object is needed, If \verb'lock' is true, the object is {\em locked}:
a call to \verb'lua_getlocked' that means the object will not be garbage collected.
Notice that an unlocked reference may be garbage collected.
Whenever the referenced object is needed,
a call to \verb'lua_getref'
returns a handle to it, returns a handle to it,
while \verb'lua_pushlocked' pushes the handle on the stack. while \verb'lua_pushref' pushes the object on the stack.
When a locked object is no longer needed, If the object has been collected,
it can be unlocked with a call to \verb'lua_unlock'. \verb'lua_getref' returns \verb'LUA_NOOBJECT',
and \verb'lua_pushobject' issues an error.
When a reference is no longer needed,
it can be freed with a call to \verb'lua_unref'.
@ -1839,12 +1848,14 @@ as illustrated in Figure~\ref{Cinher}.
\begin{figure} \begin{figure}
\Line \Line
\begin{verbatim} \begin{verbatim}
int lockedParentName; /* stores the lock index for the string "parent" */ #include "lua.h"
int lockedOldIndex; /* previous fallback function */
lua_Reference lockedParentName; /* lock index for the string "parent" */
lua_Reference lockedOldIndex; /* previous fallback function */
void callOldFallback (lua_Object table, lua_Object index) void callOldFallback (lua_Object table, lua_Object index)
{ {
lua_Object oldIndex = lua_getlocked(lockedOldIndex); lua_Object oldIndex = lua_getref(lockedOldIndex);
lua_pushobject(table); lua_pushobject(table);
lua_pushobject(index); lua_pushobject(index);
lua_callfunction(oldIndex); lua_callfunction(oldIndex);
@ -1861,7 +1872,7 @@ void Index (void)
return; return;
} }
lua_pushobject(table); lua_pushobject(table);
lua_pushlocked(lockedParentName); lua_pushref(lockedParentName);
parent = lua_getsubscript(); parent = lua_getsubscript();
if (lua_istable(parent)) if (lua_istable(parent))
{ {
@ -1880,9 +1891,9 @@ void Index (void)
This code must be registered with: This code must be registered with:
\begin{verbatim} \begin{verbatim}
lua_pushstring("parent"); lua_pushstring("parent");
lockedParentName = lua_lock(); lockedParentName = lua_ref(1);
lua_pushobject(lua_setfallback("index", Index)); lua_pushobject(lua_setfallback("index", Index));
lockedOldIndex = lua_lock(); lockedOldIndex = lua_ref(1);
\end{verbatim} \end{verbatim}
Notice how the string \verb'"parent"' is kept Notice how the string \verb'"parent"' is kept
locked in Lua for optimal performance. locked in Lua for optimal performance.
@ -1892,6 +1903,9 @@ There are many different ways to do object-oriented programming in Lua.
This section presents one possible way to This section presents one possible way to
implement classes, implement classes,
using the inheritance mechanism presented above. using the inheritance mechanism presented above.
{\em Please notice: the following examples only work
with the index fallback redefined according to
Section~\ref{exfallback}}.
As one could expect, a good way to represent a class is As one could expect, a good way to represent a class is
as a table. as a table.
@ -2079,9 +2093,12 @@ have been superseded by the new version of function \verb'date'.
Function \verb'int2str' (from \verb'strlib') has been superseded by new Function \verb'int2str' (from \verb'strlib') has been superseded by new
function \verb'format', with parameter \verb'"%c"'. function \verb'format', with parameter \verb'"%c"'.
\item \item
The lock mechanism has been superseded by the reference mechanism.
However, \verb-lua.h- provides compatibility macros,
so there is no need to change programs.
\item
API function \verb'lua_pushliteral' now is just a macro to API function \verb'lua_pushliteral' now is just a macro to
\verb'lua_pushstring'. \verb'lua_pushstring'.
Programmers are encouraged not to use this macro.
\end{itemize} \end{itemize}
\subsection*{Incompatibilities with \Index{version 2.1}} \subsection*{Incompatibilities with \Index{version 2.1}}

View File

@ -3,7 +3,7 @@
** Mathematics library to LUA ** Mathematics library to LUA
*/ */
char *rcs_mathlib="$Id: mathlib.c,v 1.13 1995/11/10 17:54:31 roberto Exp roberto $"; char *rcs_mathlib="$Id: mathlib.c,v 1.14 1996/02/09 17:21:27 roberto Exp roberto $";
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
@ -104,7 +104,7 @@ static void math_sqrt (void)
lua_pushnumber (sqrt(d)); lua_pushnumber (sqrt(d));
} }
static int old_pow; static lua_Reference old_pow;
static void math_pow (void) static void math_pow (void)
{ {
@ -113,7 +113,7 @@ static void math_pow (void)
lua_Object op = lua_getparam(3); lua_Object op = lua_getparam(3);
if (!lua_isnumber(o1) || !lua_isnumber(o2) || *(lua_getstring(op)) != 'p') if (!lua_isnumber(o1) || !lua_isnumber(o2) || *(lua_getstring(op)) != 'p')
{ {
lua_Object old = lua_getlocked(old_pow); lua_Object old = lua_getref(old_pow);
lua_pushobject(o1); lua_pushobject(o1);
lua_pushobject(o2); lua_pushobject(o2);
lua_pushobject(op); lua_pushobject(op);
@ -223,5 +223,5 @@ void mathlib_open (void)
lua_register ("random", math_random); lua_register ("random", math_random);
lua_register ("randomseed", math_randomseed); lua_register ("randomseed", math_randomseed);
old_pow = lua_lockobject(lua_setfallback("arith", math_pow)); old_pow = lua_refobject(lua_setfallback("arith", math_pow), 1);
} }

View File

@ -3,7 +3,7 @@
** TecCGraf - PUC-Rio ** TecCGraf - PUC-Rio
*/ */
char *rcs_opcode="$Id: opcode.c,v 3.65 1996/03/21 18:55:02 roberto Exp roberto $"; char *rcs_opcode="$Id: opcode.c,v 3.66 1996/03/22 19:12:15 roberto Exp roberto $";
#include <setjmp.h> #include <setjmp.h>
#include <stdio.h> #include <stdio.h>
@ -717,27 +717,31 @@ void *lua_getuserdata (lua_Object object)
} }
lua_Object lua_getlocked (int ref) lua_Object lua_getref (lua_Reference ref)
{ {
adjustC(0); Object *o = luaI_getref(ref);
*top = *luaI_getlocked(ref); if (o == NULL)
incr_top; return LUA_NOOBJECT;
CBase++; /* incorporate object in the stack */ adjustC(0);
return Ref(top-1); luaI_pushobject(o);
CBase++; /* incorporate object in the stack */
return Ref(top-1);
} }
void lua_pushlocked (int ref) void lua_pushref (lua_Reference ref)
{ {
*top = *luaI_getlocked(ref); Object *o = luaI_getref(ref);
incr_top; if (o == NULL)
lua_error("access to invalid (possibly garbage collected) reference");
luaI_pushobject(o);
} }
int lua_lock (void) lua_Reference lua_ref (int lock)
{ {
adjustC(1); adjustC(1);
return luaI_lock(--top); return luaI_ref(--top, lock);
} }
@ -812,20 +816,12 @@ void lua_pushcfunction (lua_CFunction fn)
*/ */
void lua_pushusertag (void *u, int tag) void lua_pushusertag (void *u, int tag)
{ {
if (tag < LUA_T_USERDATA) return; if (tag < LUA_T_USERDATA)
lua_error("invalid tag in `lua_pushusertag'");
tag(top) = tag; uvalue(top) = u; tag(top) = tag; uvalue(top) = u;
incr_top; incr_top;
} }
/*
** Push a lua_Object to stack.
*/
void lua_pushobject (lua_Object o)
{
*top = *Address(o);
incr_top;
}
/* /*
** Push an object on the stack. ** Push an object on the stack.
*/ */
@ -835,6 +831,16 @@ void luaI_pushobject (Object *o)
incr_top; incr_top;
} }
/*
** Push a lua_Object on stack.
*/
void lua_pushobject (lua_Object o)
{
if (o == LUA_NOOBJECT)
lua_error("attempt to push a NOOBJECT");
luaI_pushobject(Address(o));
}
int lua_type (lua_Object o) int lua_type (lua_Object o)
{ {
if (o == LUA_NOOBJECT) if (o == LUA_NOOBJECT)

21
table.c
View File

@ -3,7 +3,7 @@
** Module to control static tables ** Module to control static tables
*/ */
char *rcs_table="$Id: table.c,v 2.50 1996/03/21 16:31:32 roberto Exp roberto $"; char *rcs_table="$Id: table.c,v 2.51 1996/03/21 18:54:29 roberto Exp roberto $";
#include "mem.h" #include "mem.h"
#include "opcode.h" #include "opcode.h"
@ -170,6 +170,24 @@ int lua_markobject (Object *o)
return 0; return 0;
} }
/*
* returns 0 if the object is going to be (garbage) collected
*/
int luaI_ismarked (Object *o)
{
switch (o->tag)
{
case LUA_T_STRING:
return o->value.ts->marked;
case LUA_T_FUNCTION:
return o->value.tf->marked;
case LUA_T_ARRAY:
return o->value.a->mark;
default: /* nil, number, cfunction, or user data */
return 1;
}
}
/* /*
** Garbage collection. ** Garbage collection.
@ -182,6 +200,7 @@ Long luaI_collectgarbage (void)
lua_travsymbol(lua_markobject); /* mark symbol table objects */ lua_travsymbol(lua_markobject); /* mark symbol table objects */
luaI_travlock(lua_markobject); /* mark locked objects */ luaI_travlock(lua_markobject); /* mark locked objects */
luaI_travfallbacks(lua_markobject); /* mark fallbacks */ luaI_travfallbacks(lua_markobject); /* mark fallbacks */
luaI_invalidaterefs();
recovered += lua_strcollector(); recovered += lua_strcollector();
recovered += lua_hashcollector(); recovered += lua_hashcollector();
recovered += luaI_funccollector(); recovered += luaI_funccollector();

View File

@ -1,7 +1,7 @@
/* /*
** Module to control static tables ** Module to control static tables
** TeCGraf - PUC-Rio ** TeCGraf - PUC-Rio
** $Id: table.h,v 2.19 1996/02/26 21:00:27 roberto Exp roberto $ ** $Id: table.h,v 2.20 1996/03/14 15:57:19 roberto Exp roberto $
*/ */
#ifndef table_h #ifndef table_h
@ -30,6 +30,7 @@ Word luaI_findconstant (TaggedString *t);
Word luaI_findconstantbyname (char *name); Word luaI_findconstantbyname (char *name);
TaggedString *luaI_createfixedstring (char *str); TaggedString *luaI_createfixedstring (char *str);
int lua_markobject (Object *o); int lua_markobject (Object *o);
int luaI_ismarked (Object *o);
Long luaI_collectgarbage (void); Long luaI_collectgarbage (void);
void lua_pack (void); void lua_pack (void);