This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: SMOB tutorial for Scwm and Guile


Greg Harvey <Greg.Harvey@thezone.net> writes:

> > MAKING AN INSTANCE OF A SMOB
> > 
> > So, after registering our SMOB, the Guile interpreter knows how to deal
> > with SMOBs of that type, but we still have not seen how to create a new
> > object of a SMOB class.  We did, however, see what a SMOB object is
> > stored internally in an earlier section.  In fact, Guile has no special
> > help for constructing SMOB instances--- you simply write a primitive
> > procedure that builds a CONS cell with the appropriate id field and a
> > pointer to just C structure, and return that SCM object.  Since this is
> > error-prone, Scwm provides a helper macro, SCWM_NEWCELL_SMOB:
> > 
> > #define SCWM_NEWCELL_SMOB(ANSWER,ID,PSMOB) \
> >    do { \
> >      SCM_NEWCELL((ANSWER)); \
> >      SCM_SETCAR((ANSWER),(ID)); \
> >      SCM_SETCDR((ANSWER),(SCM) (PSMOB)); \
> >    } while (0)
> 
> This isn't all that safe, unless you change the gc slightly;
> this would require putting SCM_SETCDR first (though if things go
> wrong, either way is going to give you, at best, a fairly cryptic
> error). 

So what is the right fix?  We actually call gh_defer_ints(),
gh_allow_ints() before and after the above macro invocation, and I was
thinking of folding them into the macro, but I remember something about
that not being necessary.  Is just switching the order of SETCDR and
SETCAR sufficient?  I can see that if a GC happened between the SETCAR
and the SETCDR that would be bad, but I'm not clear on how asynchronous
the GC is.

That this is tricky should be evidence that GUILE should provde the
above macro, not applications.

> > MARK
> > 
> > The Guile Scheme interpreter uses a simple mark and sweep garbage
> > collection algorithm.  GC algorithms are beyond the scope of this
> > document--- all you must understand is that you must recursively mark
> > any SCM object you embed in a SMOB's C structure in that SMOB's mark
> > function.  For color, we had a single SCM value embedded in the
> > scwm_color struct: the color's name (as a Scheme string, not a C
> > string).   Thus, color's mark function must mark that object to ensure
> > that it does not get freed prematurely by Guile's garbage collector:
> > 
> > SCM mark_color(SCM obj) {
> >   scmw_color *psc = COLOR(obj);
> >   SCM_SETGC8MARK(obj);
>     ^^^
> 
> This isn't needed, since the gc marks the object itself before it
> calls the smob mark function. Also, marking really should go thru
> scm_gc_mark(obj), instead of the mark macros (I really need to write
> some more complete gc docs).

Ahh, yes, I remember... it changed so that we had to remove the tests
checking if the object was already marked to skip the marking of the sub
objects since the GC would hand us an already marked object.

Thanks for the pointers... obviously it's important that I get this
stuff right! :-)

Thanks,
Greg B