Browse Source

lock mechanism seperseded by the REFERENCE mechanism.

Roberto Ierusalimschy 29 years ago
parent
commit
0ef5cf2289
9 changed files with 163 additions and 93 deletions
  1. 43 27
      fallback.c
  2. 5 3
      fallback.h
  3. 15 6
      lua.h
  4. 2 2
      luamem.h
  5. 46 29
      manual.tex
  6. 4 4
      mathlib.c
  7. 26 20
      opcode.c
  8. 20 1
      table.c
  9. 2 1
      table.h

+ 43 - 27
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;

+ 5 - 3
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

+ 15 - 6
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())

+ 2 - 2
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"
 

+ 46 - 29
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}}

+ 4 - 4
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);
 }

+ 26 - 20
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)

+ 20 - 1
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();

+ 2 - 1
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);