lref.c 2.3 KB

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