lref.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. ** $Id: lref.c,v 1.3 1999/11/22 13:12:07 roberto Exp roberto $
  3. ** REF 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_checkCparams(L, 1);
  15. if (ttype(L->top-1) == LUA_T_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, "API error - invalid parameter for function `lua_unref'");
  36. L->refArray[ref].st = L->refFree;
  37. L->refFree = ref;
  38. }
  39. }
  40. lua_Object lua_getref (lua_State *L, int ref) {
  41. if (ref == LUA_REFNIL)
  42. return luaA_putluaObject(L, &luaO_nilobject);
  43. else if (0 <= ref && ref < L->refSize &&
  44. (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
  45. return luaA_putluaObject(L, &L->refArray[ref].o);
  46. else
  47. return LUA_NOOBJECT;
  48. }
  49. void lua_beginblock (lua_State *L) {
  50. luaM_growvector(L, L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
  51. "too many nested blocks", L->stacksize);
  52. L->Cblocks[L->numCblocks] = L->Cstack;
  53. L->numCblocks++;
  54. }
  55. void lua_endblock (lua_State *L) {
  56. if (L->numCblocks <= 0)
  57. lua_error(L, "API error - no block to end");
  58. --L->numCblocks;
  59. L->Cstack = L->Cblocks[L->numCblocks];
  60. L->top = L->Cstack.base;
  61. }
  62. static int ismarked (const TObject *o) {
  63. /* valid only for locked objects */
  64. switch (o->ttype) {
  65. case LUA_T_STRING: case LUA_T_USERDATA:
  66. return o->value.ts->marked;
  67. case LUA_T_ARRAY:
  68. return o->value.a->marked;
  69. case LUA_T_CLOSURE:
  70. return o->value.cl->marked;
  71. case LUA_T_PROTO:
  72. return o->value.tf->marked;
  73. #ifdef DEBUG
  74. case LUA_T_LINE: case LUA_T_CLMARK:
  75. case LUA_T_CMARK: case LUA_T_PMARK:
  76. LUA_INTERNALERROR(L, "invalid type");
  77. #endif
  78. default: /* number or cproto */
  79. return 1;
  80. }
  81. }
  82. /* for internal debugging only; check if a link of free refs is valid */
  83. #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
  84. void luaR_invalidaterefs (lua_State *L) {
  85. int n = L->refSize;
  86. int i;
  87. for (i=0; i<n; i++) {
  88. struct ref *r = &L->refArray[i];
  89. if (r->st == HOLD && !ismarked(&r->o))
  90. r->st = COLLECTED;
  91. LUA_ASSERT(L, (r->st == LOCK && ismarked(&r->o)) ||
  92. r->st == COLLECTED ||
  93. r->st == NONEXT ||
  94. (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)),
  95. "inconsistent ref table");
  96. }
  97. LUA_ASSERT(L, VALIDLINK(L, L->refFree, n), "inconsistent ref table");
  98. }