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
*/
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;

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
#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

21
lua.h
View File

@ -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())

View File

@ -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"

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}
@ -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}
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}
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);
\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'
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}}

View File

@ -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);
}

View File

@ -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,20 +816,12 @@ 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.
*/
void lua_pushobject (lua_Object o)
{
*top = *Address(o);
incr_top;
}
/*
** Push an object on the stack.
*/
@ -835,6 +831,16 @@ void luaI_pushobject (Object *o)
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)
{
if (o == LUA_NOOBJECT)

21
table.c
View File

@ -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();

View File

@ -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);