lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issue 2376: Automatic footnotes on \null markups causes unexpected r


From: David Kastrup
Subject: Re: Issue 2376: Automatic footnotes on \null markups causes unexpected results (issue 5755058)
Date: Wed, 07 Mar 2012 14:25:27 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux)

"address@hidden" <address@hidden> writes:

> On Mar 7, 2012, at 8:48 AM, address@hidden wrote:
>
>> Given the level and amount of code you write, it might be worth
>> investing the time rereading the garbage collection chapter of the Guile
>> manual.
>> 
>
> You're right that I know nothing about guile's garbage
> collection...it'd help to know this.

In a nutshell: if an SCM object is not referenced, the garbage collector
is free to throw it and its contents away.

As a reference counts:

a) getting marked using scm_gc_mark during garbage collection (mark
phase) because another referenced object does this.  All Scheme data
structures do that to their members (with the exception of "weak" parts
of a hash table).  Our own "Scheme" objects need to do this to their
contents via their own mark subroutines (like derived_mark).

b) getting permanently "protected".  Many of our own data structures
when created with new start out in protected state (since they don't
have an SCM referencing them yet, hard to avoid) and convert into SCM
via a call to unprotect () once they are properly initialized so that
calling their mark routine does not cause uninitialized garbage to be
marked.

c) having an SCM type variable in the stack referencing it.  This is a
somewhat shaky operation since the compiler may optimize variables away
when they are no longer needed.  If that is a concern, you can use
scm_remember_upto_here_1 and its cousins to keep the SCM variables
alive.

Strictly speaking, code like

      Stencil *s = unsmob_stencil (Text_interface::interpret_markup (layout, pro
      if (!s)
        {
          programming_error ("Your numbering function needs to return a stencil.
          footnote_number_markups.push_back (SCM_EOL);
          footnote_number_stencils.push_back (Stencil (Box (Interval (0, 0), Int
        }
      else
        {
          footnote_number_markups.push_back (markup);
          footnote_number_stencils.push_back (*s);
        }
      counter++;

is already borderline.  From the time of unsmob_stencil, the returned
markup is no longer protected as an SCM object.  If
footnote_number_markups.push_back were to cause Scheme garbage
collection to trigger, *s would likely already be trashed.

If we get a multithreaded garbage collector at one point of time, you
first need to assign the result of interpret_markup to an SCM variable
and put an scm_remember_upto_here_1 on this variable after the last use
of the unsmobbed stencil pointer.  Of course, if the unsmobbed object is
part of a larger protected data structure, you need not worry all that
much.  Much of the Grob * in our code base is rather laissez-faire about
protection because the grobs are usually registered somewhere else.  For
example, Grob_info does not bother protecting its contents at all if I
remember correctly because it assumes that they will live longer than
the Grob_info because of unrelated reasons.

> I'll investigate.  It'd also be good to do a little write-up for the
> CG w/ garbage collection dos and don'ts in the LilyPond base
> (i.e. what mark_smob, derived_mark, unsmob_thingee, smobbed_copy,
> self_scm & co. all mean).

A smobbed_copy is a Scheme object with the same contents as the original
but not using it (and thus also not protecting it from collection).  A
self_scm is a Scheme object referencing the original.  unsmob gives a
pointer to the unwrapped object.  mark_smob is called during the mark
phase of a referenced object and should in turn mark all SCM objects
that it references.

-- 
David Kastrup



reply via email to

[Prev in Thread] Current Thread [Next in Thread]