{Begin SubSec Resources}
{Title Resources}
{Text

{index *PRIMARY* Resources}

Interlisp is based on the use of a storage-management system which allocates memory space for new data objects, and automatically reclaims the space when no longer in use.   More generally, Interlisp manages shared "resources", such as files, semaphors for processes, etc.  The protocols for allocating and freeing such resources resemble those of ordinary storage management.

Sometimes users need to explicitly manage the allocation of resources.  They may desire the efficiency of explicit reclamation of certain temporary data; or it may be expensive to initialize a complex data object; or there may be an application that must not allocate new cells during some critical section of code.

The file package type {lisp RESOURCES}{index RESOURCES (File Package Type)} is available to help with the definition and usage of such classes of data; the definition of a {lisp RESOURCE} specifies prototype code to do the basic management operations.  The filepkg command {lisp RESOURCES}{index RESOURCES FileCom} ({PageRef Filecom RESOURCES}) is used to save such definitions on files, and {lisp INITRESOURCES}{index INITRESOURCES FileCom} ({PageRef Filecom INITRESOURCES}) causes the initialization code to be output.

The basic needs of resource management are (1) obtaining a data item from the Lisp memory management system and configuring it to be a totally new instance of the resource in question, (2) freeing up an instance which is no longer needed, (3) getting an instance of the resource for temporary usage [whether "fresh" or a formerly freed-up instance], and (4) setting up any prerequisite global data structures and variables.  A resources definition consists of four "methods":  {lisp INIT}, {lisp NEW}, {lisp GET}, and {lisp FREE}; each "method" is a form that will specialize the definition for four corresponding user-level macros {lisp INITRESOURCE}, {lisp NEWRESOURCE}, {lisp GETRESOURCE}, and {lisp FREERESOURCE}.   {fn PUTDEF} is used to make a resources definition, and the four components are specified in a proplist:

{lispcode
(PUTDEF
   '{arg RESOURCENAME}
   'RESOURCES
   '(NEW  {arg NEW-INSTANCE-GENERATION-CODE}
     FREE {arg FREEING-UP-CODE}
     GET  {arg GET-INSTANCE-CODE}
     INIT {arg INITIALIZATION-CODE}))}

Each of the {arg xxx-CODE} forms is a form that will appear as if it were the body of a substitution macro definition for the corresponding macro [see the discussion on the macros below].


{Begin SubSec A Simple Example}
{Title A Simple Example}
{Text

Suppose one has several pieces of code which use a 256-character string as a scratch string.  One could simply generate a new string each time, but that would be inefficient if done repeatedly.  If the user can guarantee that there are no re-entrant uses of the scratch string, then it could simply be stored in a global variable.  However, if the code might be re-entrant on occasion, the program has to take precautions that two programs do not use the same scratch string at the same time.  [Note: this consideration becomes very important in a multi-process environment.  It is hard to guarantee that two processes won't be running the same code at the same time, without using elaborate locks.]  A typical tactic would be to store the scratch string in a global variable, and set the variable to {lisp NIL} whenever the string is in use (so that re-entrant usages would know to get a "new" instance).  For example, assuming the global variable {lisp TEMPSTRINGBUFFER} is initialized to {lisp NIL}:

{lispcode
[DEFINEQ (WITHSTRING NIL 
  (PROG ((BUF (OR (PROG1 TEMPSTRINGBUFFER
                              (SETQ TEMPSTRINGBUFFER NIL))
                      (ALLOCSTRING 256))))
     {rm ... use the scratch string in the variable {lisp BUF} ...}
     (SETQ TEMPSTRINGBUFFER BUF)
     (RETURN]}

Here, the basic elements of a "resource" usage may be seen: (1) a call {lisp (ALLOCSTRING 256)} allocates fresh instances of "buffer", (2) after usage is completed the instance is returned to the "free" state, by putting it back in the global variable {lisp TEMPSTRINGBUFFER} where a subsequent call will find it, (3) the prog-binding of {lisp BUF} will get an existing instance of a string buffer if there is one -- otherwise it will get a new instance which will later be available for reuse, and (4) some initialization is performed before usage of the resource (in this case, it is the setting of the global variable {lisp TEMPSTRINGBUFFER}).

Given the following resources definition:

{lispcode
(PUTDEF
   'STRINGBUFFER 
   'RESOURCES
   '(NEW  (ALLOCSTRING 256)
     FREE (SETQ TEMPSTRINGBUFFER (PROG1 . ARGS))
     GET  (OR (PROG1 TEMPSTRINGBUFFER
                  (SETQ TEMPSTRINGBUFFER NIL))
              (NEWRESOURCE TEMPSTRINGBUFFER)))
     INIT (SETQ TEMPSTRINGBUFFER NIL)))}

we could then redo the example above as 

{lispcode
(DEFINEQ (WITHSTRING NIL
   (PROG ((BUF (GETRESOURCE STRINGBUFFER)))
      {rm ... use the string in the variable {lisp BUF} ...}
      (FREERESOURCE STRINGBUFFER BUF)
      (RETURN]}

The advantage of doing the coding this way is that the resource management part of {lisp WITHSTRING} is fully contained in the expansions of {lisp GETRESOURCE} and {lisp FREERESOURCE}, and thus there is no confusion between what is {lisp WITHSTRING} code and what is resource management code.  This particuar advantage will be multiplied if there are other functions which need a "temporary" string buffer; and of course, the resultant modularity makes it much easier to contemplate minor variations on, as well as multiple clients of, the {lisp STRINGBUFFER} resource.

In fact, the scenario just shown above in the {lisp WITHSTRING} example is so commonly useful that an abbreviation has been added; if a resources definition is made with *only* a {lisp NEW} method, then appropriate {lisp FREE}, {lisp GET}, and {lisp INIT} methods will be inferred, along with a coordinated globalvar, to be parallel to the above definition.  So the above definition could be more simply written

{lispcode
(PUTDEF 'STRINGBUFFER 
        'RESOURCES
        '(NEW  (ALLOCSTRING 256)))}

and every thing would work the same.

The macro {lisp WITH-RESOURCES} simplifies the common scoping case, where at the beginning of some piece of code, there are one or more {lisp GETRESOURCE} calls the results of which are each bound to a lambda variable; and at the ending of that code a {lisp FREERESOURCE} call is done on each instance.  Since the resources are locally bound to variables with the same name as the resource itself, the definition for {lisp WITHSTRING} then simplifies to

{lispcode
(DEFINEQ (WITHSTRING NIL
   (WITH-RESOURCES (STRINGBUFFER) 
   {rm ... use the string in the variable {lisp STRINGBUFFER} ...}]}

}{End SubSec A Simple Example}



{Begin SubSec Trade-offs in More Complicated Cases}
{Title Trade-offs in More Complicated Cases}
{Text

This simple example presumes that the various functions which use the resource are generally not re-entrant.  While an occasional re-entrant use will be handled correctly (another example of the resource will simply be created), if this were to happen too often, then many of the resource requests will create and throw away new objects, which defeats one of the major purposes of using resources.  A slightly more complex {lisp GET} and {lisp FREE} method can be of much benefit in maintaining a pool of available resources;  if the resource were defined to maintain a list of "free" instances, then the {lisp GET} method could simply take one off the list and the {lisp FREE} method could just push it back onto the list.  In this simple example, the {fn SETQ} in the {lisp FREE} method defined above would just become a "{lisp push}", and the first clause of the {lisp GET} method would just be {lisp (pop TEMPSTRINGBUFFER)}

A word of caution: if the datatype of the resource is something very small that Interlisp system is "good" at allocating and reclaiming, then explicit user storage management will probably not do much better than the combination of cons/createcell and the garbage collector.  This would especially be so if more complicated {lisp GET} and {lisp FREE} methods were to be used, since their overhead would be closer to that of the built-in system facilities.  Finally, it must be considered whether retaining multiple instances of the resource is a net gain; if the re-entrant case is truly rare, it may be more worthwhile to retain at most one instance, and simply let the instances created by the rarely-used case be reclaimed in the normal course of garbage collection.

}{End SubSec Trade-offs in More Complicated Cases}


{Begin SubSec Macros for Accessing Resources}
{Title Macros for Accessing Resources}
{Text

Four user-level macros are defined for accessing resources:

{Def {Type (Macro)} {Name NEWRESOURCE}
{PrintName {lisp (NEWRESOURCE {arg RESOURCENAME}  . {arg ARGS})}}
}
{Def {Type (Macro)} {Name FREERESOURCE}
{PrintName {lisp (FREERESOURCE {arg RESOURCENAME}  . {arg ARGS})}}
}
{Def {Type (Macro)} {Name GETRESOURCE}
{PrintName {lisp (GETRESOURCE {arg RESOURCENAME}  . {arg ARGS})}}
}
{Def {Type (Macro)} {Name INITRESOURCE}
{PrintName {lisp (INITRESOURCE {arg RESOURCENAME}  . {arg ARGS})}}
}

Each of these macros behave as if they were defined as a substitution macro of the form

{lispcode
(({arg RESOURCENAME} . {arg ARGS}) {arg MACROBODY})}

where the expression {arg MACROBODY} is selected by using the "code" supplied by the corresponding method from the {arg RESOURCENAME} definition.

Note that it is possible to pass "arguments" to the user's resource allocation macros.  For example, if the {lisp GET} method for the resource {lisp FOO} is {lisp (GETFOO . ARGS)}, then {lisp (GETRESOURCE FOO X Y)} is transformed into {lisp (GETFOO X Y)}.  This form was used in the {lisp FREE} method of the {lisp STRINGBUFFER} resource described above, to pass the old {lisp STRINGBUFFER} object to be freed.


{Def {Type (Macro)} {Name WITH-RESOURCES}
{PrintName {lisp (WITH-RESOURCES ({arg RESOURCE{sub 1}} {arg RESOURCE{sub 2}} {ellipsis})  {arg FORM{sub 1}} {arg FORM{sub 2}} {ellipsis})}}
}

The {lisp WITH-RESOURCES} macro binds lambda variables of the same name as the resources (for each of the resources {arg RESOURCE{sub 1}}, {arg RESOURCE{sub 2}}, etc.) to the result of the {lisp GETRESOURCE} macro; then executes the forms {arg FORM{sub 1}}, {arg FORM{sub 2}}, etc., does a {lisp FREERESOURCE} on each instance, and returns the value of the last form (evaluated and saved before the {lisp FREERESOURCE}s).

Note:  {lisp (WITH-RESOURCES {arg RESOURCE} {ellipsis})} is interpreted the same as {lisp (WITH-RESOURCES ({arg RESOURCE}) {ellipsis})}.  Also, the singular name {lisp WITH-RESOURCE}{index WITH-RESOURCE (Macro)} is accepted as a synonym for {lisp WITH-RESOURCES}.

}{End SubSec Macros for Accessing Resources}


{Begin SubSec Saving Resources in a File}
{Title Saving Resources in a File}
{Text

Resources definitions may be saved on files using the {lisp RESOURCES}{index RESOURCES FileCom} file package command ({PageRef Filecom RESOURCES}).  Typically, one only needs the full definition available when compiling or interpreting the code, so it is appropriate to put the file package command in a {lisp (DECLARE: EVAL@COMPILE DONTCOPY ...)} declaration, just as one might do for a {lisp RECORDS} declaration.  But just as certain record declarations need *some* initialization in the run-time environment, so do most resources.  This initialization is specified by the resource's {lisp INIT} method, which is executed automatically when the resource is defined by the {fn PUTDEF} output by the {lisp RESOURCES} command.   However, if the {lisp RESOURCES} command is in a {lisp DONTCOPY} expression and thus is not included in the compiled file, then it is necessary to include a separate {lisp INITRESOURCES}{index INITRESOURCES FileCom} command ({PageRef Filecom INITRESOURCES}) in the filecoms to insure that the resource is properly initialized.

}{End SubSec Saving Resources in a File}


}{End SubSec Resources}