lref.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. ** $Id: lref.c,v 1.10 2000/03/27 20:10:21 roberto Exp roberto $
  3. ** reference mechanism
  4. ** See Copyright Notice in lua.h
  5. */
  6. #define LUA_REENTRANT
  7. #include "lapi.h"
  8. #include "lmem.h"
  9. #include "lref.h"
  10. #include "lstate.h"
  11. #include "lua.h"
  12. int lua_ref (lua_State *L, int lock) {
  13. int ref;
  14. luaA_checkCargs(L, 1);
  15. if (ttype(L->top-1) == TAG_NIL)
  16. ref = LUA_REFNIL;
  17. else {
  18. if (L->refFree != NONEXT) { /* is there a free place? */
  19. ref = L->refFree;
  20. L->refFree = L->refArray[ref].st;
  21. }
  22. else { /* no more free places */
  23. luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref, refEM, MAX_INT);
  24. ref = L->refSize++;
  25. }
  26. L->refArray[ref].o = *(L->top-1);
  27. L->refArray[ref].st = lock ? LOCK : HOLD;
  28. }
  29. L->top--;
  30. return ref;
  31. }
  32. void lua_unref (lua_State *L, int ref) {
  33. if (ref >= 0) {
  34. if (ref >= L->refSize || L->refArray[ref].st >= 0)
  35. lua_error(L, "Lua API error - "
  36. "invalid argument for function `lua_unref'");
  37. L->refArray[ref].st = L->refFree;
  38. L->refFree = ref;
  39. }
  40. }
  41. lua_Object lua_getref (lua_State *L, int ref) {
  42. if (ref == LUA_REFNIL)
  43. return luaA_putluaObject(L, &luaO_nilobject);
  44. else if (0 <= ref && ref < L->refSize &&
  45. (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
  46. return luaA_putluaObject(L, &L->refArray[ref].o);
  47. else
  48. return LUA_NOOBJECT;
  49. }
  50. void lua_beginblock (lua_State *L) {
  51. luaM_growvector(L, L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
  52. "too many nested blocks", L->stacksize);
  53. L->Cblocks[L->numCblocks] = L->Cstack;
  54. L->numCblocks++;
  55. }
  56. void lua_endblock (lua_State *L) {
  57. if (L->numCblocks <= 0)
  58. lua_error(L, "Lua API error - no block to end");
  59. --L->numCblocks;
  60. L->Cstack = L->Cblocks[L->numCblocks];
  61. L->top = L->Cstack.base;
  62. }
  63. static int ismarked (const TObject *o) {
  64. /* valid only for locked objects */
  65. switch (o->ttype) {
  66. case TAG_STRING: case TAG_USERDATA:
  67. return o->value.ts->marked;
  68. case TAG_TABLE:
  69. return o->value.a->marked;
  70. case TAG_LCLOSURE: case TAG_CCLOSURE:
  71. return o->value.cl->marked;
  72. default: /* number */
  73. return 1;
  74. }
  75. }
  76. /* for internal debugging only; check if a link of free refs is valid */
  77. #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
  78. void luaR_invalidaterefs (lua_State *L) {
  79. int n = L->refSize;
  80. int i;
  81. for (i=0; i<n; i++) {
  82. struct Ref *r = &L->refArray[i];
  83. if (r->st == HOLD && !ismarked(&r->o))
  84. r->st = COLLECTED;
  85. LUA_ASSERT(L, (r->st == LOCK && ismarked(&r->o)) ||
  86. r->st == COLLECTED ||
  87. r->st == NONEXT ||
  88. (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)),
  89. "inconsistent ref table");
  90. }
  91. LUA_ASSERT(L, VALIDLINK(L, L->refFree, n), "inconsistent ref table");
  92. }