lref.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. ** $Id: lref.c,v 1.2 1999/11/10 15:37:50 roberto Exp roberto $
  3. ** REF mechanism
  4. ** See Copyright Notice in lua.h
  5. */
  6. #define LUA_REENTRANT
  7. #include "lmem.h"
  8. #include "lref.h"
  9. #include "lstate.h"
  10. #include "lua.h"
  11. int luaR_ref (lua_State *L, const TObject *o, int lock) {
  12. int ref;
  13. if (ttype(o) == LUA_T_NIL)
  14. ref = LUA_REFNIL;
  15. else {
  16. if (L->refFree != NONEXT) { /* is there a free place? */
  17. ref = L->refFree;
  18. L->refFree = L->refArray[ref].st;
  19. }
  20. else { /* no more free places */
  21. luaM_growvector(L, L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT);
  22. ref = L->refSize++;
  23. }
  24. L->refArray[ref].o = *o;
  25. L->refArray[ref].st = lock ? LOCK : HOLD;
  26. }
  27. return ref;
  28. }
  29. void lua_unref (lua_State *L, int ref) {
  30. if (ref >= 0) {
  31. if (ref >= L->refSize || L->refArray[ref].st >= 0)
  32. lua_error(L, "API error - invalid parameter for function `lua_unref'");
  33. L->refArray[ref].st = L->refFree;
  34. L->refFree = ref;
  35. }
  36. }
  37. const TObject *luaR_getref (lua_State *L, int ref) {
  38. if (ref == LUA_REFNIL)
  39. return &luaO_nilobject;
  40. else if (0 <= ref && ref < L->refSize &&
  41. (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
  42. return &L->refArray[ref].o;
  43. else
  44. return NULL;
  45. }
  46. static int ismarked (const TObject *o) {
  47. /* valid only for locked objects */
  48. switch (o->ttype) {
  49. case LUA_T_STRING: case LUA_T_USERDATA:
  50. return o->value.ts->marked;
  51. case LUA_T_ARRAY:
  52. return o->value.a->marked;
  53. case LUA_T_CLOSURE:
  54. return o->value.cl->marked;
  55. case LUA_T_PROTO:
  56. return o->value.tf->marked;
  57. #ifdef DEBUG
  58. case LUA_T_LINE: case LUA_T_CLMARK:
  59. case LUA_T_CMARK: case LUA_T_PMARK:
  60. LUA_INTERNALERROR(L, "invalid type");
  61. #endif
  62. default: /* number or cproto */
  63. return 1;
  64. }
  65. }
  66. /* for internal debugging only; check if a link of free refs is valid */
  67. #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
  68. void luaR_invalidaterefs (lua_State *L) {
  69. int n = L->refSize;
  70. int i;
  71. for (i=0; i<n; i++) {
  72. struct ref *r = &L->refArray[i];
  73. if (r->st == HOLD && !ismarked(&r->o))
  74. r->st = COLLECTED;
  75. LUA_ASSERT(L, (r->st == LOCK && ismarked(&r->o)) ||
  76. r->st == COLLECTED ||
  77. r->st == NONEXT ||
  78. (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)),
  79. "inconsistent ref table");
  80. }
  81. LUA_ASSERT(L, VALIDLINK(L, L->refFree, n), "inconsistent ref table");
  82. }