DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

(guile.info.gz) Garbage Collecting Smobs

Info Catalog (guile.info.gz) Type checking (guile.info.gz) Defining New Types (Smobs) (guile.info.gz) A Common Mistake In Allocating Smobs
 
 18.3.4 Garbage Collecting Smobs
 -------------------------------
 
 Once a smob has been released to the tender mercies of the Scheme
 system, it must be prepared to survive garbage collection.  Guile calls
 the `mark' and `free' functions of the `scm_smobfuns' structure to
 manage this.
 
    As described before ( Conservative GC), every object in the
 Scheme system has a "mark bit", which the garbage collector uses to
 tell live objects from dead ones.  When collection starts, every
 object's mark bit is clear.  The collector traces pointers through the
 heap, starting from objects known to be live, and sets the mark bit on
 each object it encounters.  When it can find no more unmarked objects,
 the collector walks all objects, live and dead, frees those whose mark
 bits are still clear, and clears the mark bit on the others.
 
    The two main portions of the collection are called the "mark phase",
 during which the collector marks live objects, and the "sweep phase",
 during which the collector frees all unmarked objects.
 
    The mark bit of a smob lives in a special memory region.  When the
 collector encounters a smob, it sets the smob's mark bit, and uses the
 smob's type tag to find the appropriate `mark' function for that smob:
 the one listed in that smob's `scm_smobfuns' structure.  It then calls
 the `mark' function, passing it the smob as its only argument.
 
    The `mark' function is responsible for marking any other Scheme
 objects the smob refers to.  If it does not do so, the objects' mark
 bits will still be clear when the collector begins to sweep, and the
 collector will free them.  If this occurs, it will probably break, or at
 least confuse, any code operating on the smob; the smob's `SCM' values
 will have become dangling references.
 
    To mark an arbitrary Scheme object, the `mark' function may call
 this function:
 
  -- Function: void scm_gc_mark (SCM X)
      Mark the object X, and recurse on any objects X refers to.  If X's
      mark bit is already set, return immediately.
 
    Thus, here is how we might write the `mark' function for the image
 smob type discussed above:
 
      SCM
      mark_image (SCM image_smob)
      {
        /* Mark the image's name and update function.  */
        struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
        scm_gc_mark (image->name);
        scm_gc_mark (image->update_func);
 
        return SCM_BOOL_F;
      }
 
    Note that, even though the image's `update_func' could be an
 arbitrarily complex structure (representing a procedure and any values
 enclosed in its environment), `scm_gc_mark' will recurse as necessary
 to mark all its components.  Because `scm_gc_mark' sets an object's
 mark bit before it recurses, it is not confused by circular structures.
 
    As an optimization, the collector will mark whatever value is
 returned by the `mark' function; this helps limit depth of recursion
 during the mark phase.  Thus, the code above could also be written as:
      SCM
      mark_image (SCM image_smob)
      {
        /* Mark the image's name and update function.  */
        struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
        scm_gc_mark (image->name);
        return image->update_func;
      }
 
    Finally, when the collector encounters an unmarked smob during the
 sweep phase, it uses the smob's tag to find the appropriate `free'
 function for the smob.  It then calls the function, passing it the smob
 as its only argument.
 
    The `free' function must release any resources used by the smob.
 However, it need not free objects managed by the collector; the
 collector will take care of them.  The return type of the `free'
 function should be `size_t', an unsigned integral type; the `free'
 function should return the number of bytes released, to help the
 collector maintain statistics on the size of the heap.
 
    Here is how we might write the `free' function for the image smob
 type:
      size_t
      free_image (SCM image_smob)
      {
        struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
        size_t size = image->width * image->height + sizeof (*image);
 
        free (image->pixels);
        free (image);
 
        return size;
      }
 
    During the sweep phase, the garbage collector will clear the mark
 bits on all live objects.  The code which implements a smob need not do
 this itself.
 
    There is no way for smob code to be notified when collection is
 complete.
 
    It is usually a good idea to minimize the amount of processing done
 during garbage collection; keep `mark' and `free' functions very
 simple.  Since collections occur at unpredictable times, it is easy for
 any unusual activity to interfere with normal code.
 
Info Catalog (guile.info.gz) Type checking (guile.info.gz) Defining New Types (Smobs) (guile.info.gz) A Common Mistake In Allocating Smobs
automatically generated byinfo2html