home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / pty4 / part03 / ralloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-19  |  3.7 KB  |  151 lines

  1. /* ralloc.c, ralloc.h: recovering alloc
  2. Daniel J. Bernstein, brnstnd@nyu.edu.
  3. Depends on sod.h.
  4. Requires malloc/free.
  5. 8/26/91: Changed exit() to _exit().
  6. 8/26/91: Made rallocneverfail() overwrite any previous handler.
  7. 7/24/91: Added rallocneverfail().
  8. 7/18/91: Baseline. ralloc 1.0, public domain.
  9. No known patent problems.
  10.  
  11. Lots of library routines allocate space for temporary objects: compiled
  12. regular expressions, for example. They don't destroy the objects between
  13. each call---wouldn't it be a waste to reallocate and recompile those
  14. regular expressions on every single pattern match? But when space gets
  15. tight, you don't want all those temporary objects cluttering the heap.
  16. You've got to deallocate them as soon as possible. Sure, library X might
  17. have some deallocation routines---but if X is hidden below library Y and
  18. separate library A runs out of space, do you expect A to know about X
  19. and call X's routines? Of course not. How can A and X coordinate?
  20.  
  21. The solution is ralloc. ralloc works just like malloc, except that when
  22. it runs out of memory, it tries to recover space from anyone who's
  23. willing to give a little slack. If f is a deallocation function, you can
  24. call rallocinstall(f), and ralloc(n) will call f() if there aren't n
  25. bytes free. f() should return a non-zero integer if it could free some
  26. memory, 0 if not. Several libraries can rallocinstall their deallocation
  27. routines, and ralloc will cycle between all of them. Make sure that f
  28. actually frees some memory if it returns non-zero---otherwise ralloc()
  29. will loop, trying f again and again and wondering why malloc() never has
  30. enough space. (In a future implementation I might add a loop counter and
  31. have ralloc give up after trying f enough times.)
  32.  
  33. According to John F. Haugh, ralloc is a Bad Thing, because it inherently
  34. requires static variables, hence can't be put into a ``pure'' shared
  35. library. Face it, John: ralloc() solves a real problem, and if you can't
  36. put it in a shared library, it's not because ralloc() is somehow evil.
  37. It's because your shared libraries aren't good enough.
  38.  
  39. */
  40.  
  41. #include "ralloc.h"
  42. #include "sod.h"
  43. extern char *malloc(); /*XXXX*/
  44. extern void free();
  45.  
  46. typedef int (*foo)();
  47.  
  48. SODdecl(funlist,foo);
  49.  
  50. static funlist funhead = 0;
  51. static funlist funlast = 0; /* last fun to successfully recover */
  52.  
  53. static int ralloccount = 0;
  54.  
  55. int rcount()
  56. {
  57.  return ralloccount;
  58. }
  59.  
  60. void rfree(s)
  61. char *s;
  62. {
  63.  /* This is for completeness, and for another reason: so that you only */
  64.  /* have to modify this file if you want a debugging malloc-free. */
  65.  --ralloccount; /* for instance */
  66.  free(s);
  67. }
  68.  
  69. static int crit = 0; /* just to be safe */
  70.  
  71. static int (*neverfail)() = 0;
  72.  
  73. static void die(n)
  74. unsigned n;
  75. {
  76.  if (neverfail)
  77.    neverfail(n);
  78.  _exit(1); /*XXX*/
  79. }
  80.  
  81. char *ralloc(n)
  82. unsigned n;
  83. {
  84.  char *t;
  85.  funlist fun;
  86.  
  87.  if(t = malloc(n))
  88.   {
  89.    ++ralloccount;
  90.    return t;
  91.   }
  92.  if (crit)
  93.    if (neverfail)
  94.      die(n);
  95.    else
  96.      return 0;
  97.  if (!funhead)
  98.    if (neverfail)
  99.      die(n);
  100.    else
  101.      return 0;
  102.  crit = 1;
  103.  fun = (funlast ? SODnext(funlast) : funhead);
  104.  do
  105.   {
  106.    if(!fun)
  107.      fun = funhead;
  108.    if((*SODdata(fun))()) /* XXX: can we make use of args or return code? */
  109.      funlast = fun;
  110.    else
  111.      if(fun == funlast)
  112.       {
  113.        crit = 0;
  114.        if (neverfail)
  115.      die(n);
  116.        else
  117.          return 0; /* gaack! */
  118.       }
  119.    fun = SODnext(fun);
  120.    t = malloc(n);
  121.   }
  122.  while(!t);
  123.  ++ralloccount;
  124.  crit = 0;
  125.  return t;
  126. }
  127.  
  128. void rallocneverfail(f)
  129. int (*f)();
  130. {
  131.  neverfail = f; /* possibly overwriting previous handler */
  132. }
  133.  
  134. #define malloc ralloc
  135.  
  136. int rallocinstall(f)
  137. int (*f)();
  138. {
  139.  funlist fun;
  140.  
  141.  fun = SODalloc(funlist,fun,ralloc);
  142.  if(!fun)
  143.    return -1;
  144.  SODdata(fun) = f;
  145.  SODpush(funhead,fun);
  146.  
  147.  funlast = funhead; /* need to set it to something */
  148.  
  149.  return 0;
  150. }
  151.