home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / reference.c < prev    next >
C/C++ Source or Header  |  1995-07-03  |  7KB  |  290 lines

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /******************************************************\
  5. *                                *
  6. * reference.c:                           *
  7. * reference count management and other storage issues  *
  8. *                                *
  9. \******************************************************/
  10.  
  11. #include        "EXTERN.h"
  12. #include     "wool.h"
  13.  
  14.  
  15. /*
  16.  * The memory management of WOOL is implemented via a differed reference
  17.  * count. That, each time an object's reference count attains 0, it is put in
  18.  * the zrt, which is polled at regular intervals
  19.  */
  20.  
  21. /************************************\
  22. *                      *
  23. * Zero_reference table module (zrt)  *
  24. *                      *
  25. \************************************/
  26.  
  27. /*
  28.  * The zrt (Zero Reference Table) global structure  is used to mark ALL wobs
  29.  * that have at any moment be of REF 0, that is either being created or via
  30.  * decrease_reference.  Then you can call zrt_gc at strategic moments, (ie in
  31.  * no enclosing WOOL function) to free all the zero-referenced objects in the
  32.  * zrt.
  33.  */
  34.  
  35. #ifdef STATS
  36. WOOL_OBJECT
  37. zrtstats()
  38. {
  39.     wool_printf("Zero-reference-table has %d", zrt_size);
  40.     wool_printf("/%d slots\n", zrt_limit);
  41.     return NIL;
  42. }
  43. #endif /* STATS */
  44.  
  45. zrt_init()
  46. {
  47.     zrt_size = 0;
  48.     zrt_limit = 63;    /* pow(2,n)/4 -1 */
  49.     zrt = (WOOL_OBJECT *) Malloc(zrt_limit * sizeof(WOOL_OBJECT));
  50.     zrt_last = zrt;
  51. }
  52.  
  53. /*
  54.  * disposes really of objects stacked in zrt. Be warned that a WOOL_free might
  55.  * trigger zrt_put during the zrt_gc !
  56.  */
  57.  
  58. static int WlZrtInGc = 0;
  59.  
  60. zrt_gc(from)
  61. int    from;
  62. {
  63.     WOOL_OBJECT *zrt_from = zrt + from;
  64.  
  65.     WlZrtInGc = 1;
  66.     while (zrt_last > zrt_from) {
  67.     zrt_last--, zrt_size--;
  68.     if (REF(*zrt_last)) {    /* ok, graduate to normal object */
  69.         (*zrt_last) -> reference_count |= 1;
  70.     } else {        /* free it */
  71.         WOOL_send(WOOL_free, *zrt_last, (*zrt_last));
  72.     }
  73.     }
  74.     WlZrtInGc = 0;
  75. }
  76.  
  77. /*
  78.  * Never call zrt_put if obj was already in it (sould not happen)
  79.  */
  80.  
  81. WOOL_OBJECT
  82. zrt_put(obj)
  83. WOOL_OBJECT obj;
  84. {
  85.     WOOL_OBJECT    *old_zrt;
  86.  
  87. #ifdef DEBUG
  88.     must_not_be_in_zrt(obj);
  89. #endif                    /* DEBUG */
  90.     if (WlZrtInGc) {
  91.     WOOL_send(WOOL_free, obj, (obj));
  92.     } else {
  93.     if(zrt_size == zrt_limit) {
  94.         zrt_limit = (zrt_limit + 1) * 2 -1;
  95.         old_zrt = zrt;
  96.         zrt = (WOOL_OBJECT *) Realloc(zrt, zrt_limit *
  97.                       sizeof(WOOL_OBJECT));
  98.         zrt_last = zrt + (zrt_last - old_zrt);
  99.     }
  100.     zrt_size ++;
  101.     obj -> reference_count = 0;
  102.     return *zrt_last++ = obj;
  103.     }
  104. }
  105.  
  106. /* when an object is physically replaced by another, update its entry
  107.  * in the zrt
  108.  */
  109.  
  110. zrt_replace_element(old, new)
  111. WOOL_OBJECT old;
  112. WOOL_OBJECT new;
  113. {
  114.     WOOL_OBJECT    *zrt_ptr = zrt;
  115.  
  116.     while (zrt_ptr < zrt_last) {
  117.     if (*zrt_ptr == old) {
  118.         *zrt_ptr = new;
  119.         return;
  120.     }
  121.     zrt_ptr++;
  122.     }
  123. #ifdef DEBUG
  124.     wool_error("replaced object 0x%x was not in zrt!", old);
  125. #endif /* DEBUG */
  126. }
  127.  
  128. #ifdef DEBUG
  129. /* checks that the element is not in fact already in the zrt...
  130.  */
  131.  
  132. must_not_be_in_zrt(obj)
  133. WOOL_OBJECT obj;
  134. {
  135.     WOOL_OBJECT    *zrt_ptr = zrt;
  136.  
  137.     while (zrt_ptr < zrt_last) {
  138.     if (*zrt_ptr == obj) {
  139.         wool_printf("at zrt[%d]", zrt_last - zrt);
  140.         wool_printf(" and zrt[%d], type: ", zrt_ptr - zrt);
  141.         wool_print(wool_type(obj));
  142.         wool_puts(", obj: ");
  143.         wool_print(obj);
  144.         wool_newline();
  145.         wool_error("object 0x%x was already in zrt!", obj);
  146.     }
  147.     zrt_ptr++;
  148.     }
  149. }
  150. #endif /* DEBUG         */
  151.  
  152. /***********************\
  153. *                 *
  154. * reference management  *
  155. *                 *
  156. \***********************/
  157.  
  158. /* increase_reference is a macro (REF(x)++) */
  159.  
  160. #ifdef DEBUG            /* macro otherwise */
  161. increase_reference(obj)
  162. WOOL_OBJECT obj;    /* obj may be UNDEFINED */
  163. {
  164.     REF(obj) += 2;
  165. }
  166.  
  167. decrease_reference(obj)
  168. WOOL_OBJECT obj;    /* obj may be UNDEFINED */
  169. {
  170.     if (obj) {
  171.     if (((obj -> reference_count) -= 2) == 1)
  172.         zrt_put(obj);
  173.     else if (obj -> reference_count < 0) {
  174.         wool_print(obj);
  175.         wool_error(": reference_count became %d", obj ->
  176.                reference_count);
  177.     }
  178.     }
  179. }
  180.  
  181. decrease_reference_non_null(obj)
  182. WOOL_OBJECT obj;    /* obj must be non-nil */
  183. {
  184.     if (((obj -> reference_count) -= 2) == 1)
  185.         zrt_put(obj);
  186.     else if (obj -> reference_count < 0) {
  187.         wool_print(obj);
  188.         wool_error(": reference_count became %d", obj ->
  189.                reference_count);
  190.     }
  191. }
  192. #endif /* DEBUG */
  193.  
  194. /*
  195.  * decrease_reference_in_list:
  196.  * decrease reference count of all the elements of the list.
  197.  * but doesn't free the list.
  198.  */
  199.  
  200. decrease_reference_in_list(count, list)
  201. int    count;
  202. WOOL_OBJECT *list;
  203. {
  204.     WOOL_OBJECT *last = list + count;
  205.  
  206.     while (list < last){
  207.     decrease_reference(*list);
  208.     list++;
  209.     }
  210. }
  211.  
  212. /*
  213.  * duplicate an array of objects, increasing the reference count,
  214.  * and mallocing
  215.  */
  216.  
  217. duplicate_n_objects(source, dest, n)
  218. WOOL_OBJECT    *source;        /* source is the array */
  219. WOOL_OBJECT   **dest;        /* while dest is a POINTER to the array */
  220. int             n;        /* how many to copy */
  221. {
  222.     WOOL_OBJECT *p = source, *q, *last = source + n;
  223.  
  224.     q = *dest = (WOOL_OBJECT *) Malloc(sizeof(WOOL_OBJECT) * n);
  225.     while (p < last)
  226.         increase_reference(*q++ = *p++);
  227. }
  228.  
  229. /*
  230.  * duplicate an array of objects, increasing the reference count,
  231.  * without mallocing (dest already points to an malloced aera)
  232.  */
  233.  
  234. copy_n_objects(source, dest, n)
  235. WOOL_OBJECT    *source;        /* source is the array */
  236. WOOL_OBJECT    *dest;        /* dest is  the array */
  237. int             n;        /* how many to copy */
  238. {
  239.     WOOL_OBJECT *p = source, *q = dest, *last = source + n;
  240.  
  241.     while (p < last)
  242.     increase_reference(*q++ = *p++);
  243. }
  244.  
  245.  
  246. /************************************\
  247. *                      *
  248. * Delayed Free table module (dft)    *
  249. *                      *
  250. \************************************/
  251.  
  252. /* this table holds all memory chunks that should be freed only when at the
  253.  * top-level
  254.  */
  255.  
  256. #define INITIAL_DFT_SIZE 31    /* pow(2,n)/4 - 1 */
  257.  
  258. /* This table holds memory chunks that are to be freed at the top-level
  259.  */
  260.  
  261. dft_init()
  262. {
  263.     dft = (char **) Malloc(INITIAL_DFT_SIZE * sizeof(char *));
  264.     dft_last = dft;
  265.     dft_last_allocated = dft + INITIAL_DFT_SIZE;
  266. }
  267.  
  268. /* dft_gc disposes really of memory stacked in dft. Defined as a macro
  269.  * while (dft_last > dft) Free(*(--dft_last)) in wool.h
  270.  */
  271.  
  272. /* put in dft for later freeing
  273.  */
  274.  
  275. DelayedFree(ptr)
  276. char * ptr;
  277. {
  278.     ASSERT(ptr != NULL);
  279.     if(dft_last == dft_last_allocated) {
  280.     char    **old_dft;
  281.     int size = dft_last - dft, old_size = size;
  282.     size = (size + 1) * 2 -1;
  283.     old_dft = dft;
  284.     dft = (char **) Realloc(dft, size * sizeof(char *));
  285.     dft_last = dft + old_size;
  286.     dft_last_allocated = dft + size;
  287.     }
  288.     *dft_last++ = ptr;
  289. }
  290.