lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 0ef5cf22891c9d34a88ccc5d89eb0ed82b004471
parent fed9408ab51a4be5ff84450ad47d1e0cdaed97bc
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Mon, 22 Apr 1996 15:00:17 -0300

lock mechanism seperseded by the REFERENCE mechanism.

Diffstat:
Mfallback.c | 70+++++++++++++++++++++++++++++++++++++++++++---------------------------
Mfallback.h | 8+++++---
Mlua.h | 21+++++++++++++++------
Mluamem.h | 4++--
Mmanual.tex | 75++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mmathlib.c | 8++++----
Mopcode.c | 46++++++++++++++++++++++++++--------------------
Mtable.c | 21++++++++++++++++++++-
Mtable.h | 3++-
9 files changed, 163 insertions(+), 93 deletions(-)

diff --git a/fallback.c b/fallback.c @@ -3,7 +3,7 @@ ** 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 <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 "opcode.h" #include "lua.h" +#include "table.h" static void errorFB (void); @@ -112,59 +113,74 @@ static void funcFB (void) /* -** Lock routines +** Reference routines */ -static Object *lockArray = NULL; -static int lockSize = 0; +static struct ref { + 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 oldSize; if (tag(object) == LUA_T_NIL) - return -1; /* special lock ref for nil */ - for (i=0; i<lockSize; i++) - if (tag(&lockArray[i]) == LUA_T_NIL) - { - lockArray[i] = *object; - return i; - } + return -1; /* special ref for nil */ + for (i=0; i<refSize; i++) + if (refArray[i].status == FREE) + goto found; /* no more empty spaces */ - oldSize = lockSize; - lockSize = growvector(&lockArray, lockSize, Object, lockEM, MAX_WORD); - for (i=oldSize; i<lockSize; i++) - tag(&lockArray[i]) = LUA_T_NIL; - lockArray[oldSize] = *object; - return oldSize; + oldSize = refSize; + refSize = growvector(&refArray, refSize, struct ref, refEM, MAX_WORD); + for (i=oldSize; i<refSize; i++) + refArray[i].status = FREE; + i = 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) - tag(&lockArray[ref]) = LUA_T_NIL; + if (ref >= 0 && ref < refSize) + refArray[ref].status = FREE; } -Object *luaI_getlocked (int ref) +Object *luaI_getref (lua_Reference ref) { static Object nul = {LUA_T_NIL, {0}}; - if (ref >= 0 && ref < lockSize) - return &lockArray[ref]; - else + if (ref == -1) 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 *)) { int i; - for (i=0; i<lockSize; i++) - fn(&lockArray[i]); + for (i=0; i<refSize; 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 *)) { int i; diff --git a/fallback.h b/fallback.h @@ -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 #define fallback_h +#include "lua.h" #include "opcode.h" extern struct FB { @@ -26,9 +27,10 @@ extern struct FB { #define FB_GETGLOBAL 9 void luaI_setfallback (void); -int luaI_lock (Object *object); -Object *luaI_getlocked (int ref); +lua_Reference luaI_ref (Object *object, int lock); +Object *luaI_getref (lua_Reference ref); void luaI_travlock (int (*fn)(Object *)); +void luaI_invalidaterefs (void); char *luaI_travfallbacks (int (*fn)(Object *)); #endif diff --git a/lua.h b/lua.h @@ -2,7 +2,7 @@ ** LUA - Linguagem para Usuarios de Aplicacao ** Grupo de Tecnologia em Computacao Grafica ** 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_lock (void); -lua_Object lua_getlocked (int ref); -void lua_pushlocked (int ref); -void lua_unlock (int ref); + +typedef int lua_Reference; + +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); /* 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)) @@ -99,6 +102,12 @@ lua_Object lua_createtable (void); /* 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_getindexed(o,n) (lua_pushobject(o), lua_pushnumber(n), lua_getsubscript()) diff --git a/luamem.h b/luamem.h @@ -1,7 +1,7 @@ /* ** mem.c ** 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 @@ -18,7 +18,7 @@ #define constantEM "constant table overflow" #define stackEM "stack size overflow" #define lexEM "lex buffer overflow" -#define lockEM "lock table overflow" +#define refEM "reference table overflow" #define tableEM "table overflow" #define memEM "not enough memory" diff --git a/manual.tex b/manual.tex @@ -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} @@ -34,7 +34,7 @@ Waldemar Celes Filho \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 @@ -739,7 +739,7 @@ The API functions can be classified in the following categories: \item manipulating (reading and writing) Lua objects; \item calling Lua functions; \item C functions to be called by Lua; -\item locking Lua Objects. +\item references to Lua Objects. \end{enumerate} 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. -\subsection{Locking Lua Objects} +\subsection{References to Lua Objects} As already noted, \verb'lua_Object's are volatile. If the C code needs to keep a \verb'lua_Object' outside block boundaries, -it has to {\em lock} the object. -The routines to manipulate locking are the following: -\Deffunc{lua_lock}\Deffunc{lua_getlocked} -\Deffunc{lua_pushlocked}\Deffunc{lua_unlock} -\begin{verbatim} -int lua_lock (void); -lua_Object lua_getlocked (int ref); -void lua_pushlocked (int ref); -void lua_unlock (int ref); -\end{verbatim} -The function \verb'lua_lock' locks the object -which is on the top of the stack, -and returns a reference to it. -Whenever the locked object is needed, -a call to \verb'lua_getlocked' +it must create a \Def{reference} to the object. +The routines to manipulate references are the following: +\Deffunc{lua_ref}\Deffunc{lua_getref} +\Deffunc{lua_pushref}\Deffunc{lua_unref} +\begin{verbatim} +typedef int lua_Reference; + +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); +\end{verbatim} +The function \verb'lua_ref' creates a reference +to the object which is on the top of the stack, +and returns this reference. +If \verb'lock' is true, the object is {\em locked}: +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, -while \verb'lua_pushlocked' pushes the handle on the stack. -When a locked object is no longer needed, -it can be unlocked with a call to \verb'lua_unlock'. +while \verb'lua_pushref' pushes the object on the stack. +If the object has been collected, +\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} \Line \begin{verbatim} -int lockedParentName; /* stores the lock index for the string "parent" */ -int lockedOldIndex; /* previous fallback function */ +#include "lua.h" + +lua_Reference lockedParentName; /* lock index for the string "parent" */ +lua_Reference lockedOldIndex; /* previous fallback function */ 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(index); lua_callfunction(oldIndex); @@ -1861,7 +1872,7 @@ void Index (void) return; } lua_pushobject(table); - lua_pushlocked(lockedParentName); + lua_pushref(lockedParentName); parent = lua_getsubscript(); if (lua_istable(parent)) { @@ -1880,9 +1891,9 @@ void Index (void) This code must be registered with: \begin{verbatim} lua_pushstring("parent"); - lockedParentName = lua_lock(); + lockedParentName = lua_ref(1); lua_pushobject(lua_setfallback("index", Index)); - lockedOldIndex = lua_lock(); + lockedOldIndex = lua_ref(1); \end{verbatim} Notice how the string \verb'"parent"' is kept 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 implement classes, 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 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'format', with parameter \verb'"%c"'. \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 \verb'lua_pushstring'. -Programmers are encouraged not to use this macro. \end{itemize} \subsection*{Incompatibilities with \Index{version 2.1}} diff --git a/mathlib.c b/mathlib.c @@ -3,7 +3,7 @@ ** 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 <math.h> @@ -104,7 +104,7 @@ static void math_sqrt (void) lua_pushnumber (sqrt(d)); } -static int old_pow; +static lua_Reference old_pow; static void math_pow (void) { @@ -113,7 +113,7 @@ static void math_pow (void) lua_Object op = lua_getparam(3); 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(o2); lua_pushobject(op); @@ -223,5 +223,5 @@ void mathlib_open (void) lua_register ("random", math_random); lua_register ("randomseed", math_randomseed); - old_pow = lua_lockobject(lua_setfallback("arith", math_pow)); + old_pow = lua_refobject(lua_setfallback("arith", math_pow), 1); } diff --git a/opcode.c b/opcode.c @@ -3,7 +3,7 @@ ** 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 <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); - *top = *luaI_getlocked(ref); - incr_top; - CBase++; /* incorporate object in the stack */ - return Ref(top-1); + Object *o = luaI_getref(ref); + if (o == NULL) + return LUA_NOOBJECT; + adjustC(0); + 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); - incr_top; + Object *o = luaI_getref(ref); + 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); - return luaI_lock(--top); + return luaI_ref(--top, lock); } @@ -812,27 +816,29 @@ void lua_pushcfunction (lua_CFunction fn) */ 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; incr_top; } /* -** Push a lua_Object to stack. +** Push an object on the stack. */ -void lua_pushobject (lua_Object o) +void luaI_pushobject (Object *o) { - *top = *Address(o); + *top = *o; incr_top; } /* -** Push an object on the stack. +** Push a lua_Object on stack. */ -void luaI_pushobject (Object *o) +void lua_pushobject (lua_Object o) { - *top = *o; - incr_top; + if (o == LUA_NOOBJECT) + lua_error("attempt to push a NOOBJECT"); + luaI_pushobject(Address(o)); } int lua_type (lua_Object o) diff --git a/table.c b/table.c @@ -3,7 +3,7 @@ ** 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 "opcode.h" @@ -170,6 +170,24 @@ int lua_markobject (Object *o) 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. @@ -182,6 +200,7 @@ Long luaI_collectgarbage (void) lua_travsymbol(lua_markobject); /* mark symbol table objects */ luaI_travlock(lua_markobject); /* mark locked objects */ luaI_travfallbacks(lua_markobject); /* mark fallbacks */ + luaI_invalidaterefs(); recovered += lua_strcollector(); recovered += lua_hashcollector(); recovered += luaI_funccollector(); diff --git a/table.h b/table.h @@ -1,7 +1,7 @@ /* ** Module to control static tables ** 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 @@ -30,6 +30,7 @@ Word luaI_findconstant (TaggedString *t); Word luaI_findconstantbyname (char *name); TaggedString *luaI_createfixedstring (char *str); int lua_markobject (Object *o); +int luaI_ismarked (Object *o); Long luaI_collectgarbage (void); void lua_pack (void);