lilypond-devel
[Top][All Lists]
Advanced

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

Re: Guile GC in C++


From: David Kastrup
Subject: Re: Guile GC in C++
Date: Tue, 06 Jul 2021 10:59:27 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Jean Abou Samra <jean@abou-samra.fr> writes:

> Hello,
>
> I am struggling to understand how to write
> C++ code that correctly protects and unprotects
> smobs from GC. Take this code from lily/grob-pq-engraver.cc:
>
> void
> Grob_pq_engraver::process_acknowledged ()
> {
>   std::sort (started_now_.begin (), started_now_.end ());
>   SCM lst = SCM_EOL;
>   SCM *tail = &lst;
>   for (vsize i = 0; i < started_now_.size (); i++)
>     {
>       *tail = scm_acons (started_now_[i].end_.smobbed_copy (),
>                          started_now_[i].grob_->self_scm (),
>                          SCM_EOL);
>       tail = SCM_CDRLOC (*tail);
>     }
>
>   SCM busy = get_property (this, "busyGrobs");
>   busy = scm_merge_x (lst, busy, ly_grob_pq_less_p_proc);
>   set_property (context (), "busyGrobs", busy);
>
>   started_now_.clear ();
> }
>
> Looks nice, but what does SCM_CDRLOC do? It apparently
> takes an SCM, and returns a pointer to an SCM. What's
> the purpose?

Essentially tail = &scm_cdr (*tail);

but scm_cdr is not an lvalue.

> I can't find it documented anywhere
> in the Guile manual (whether for 1.8 or later releases).
> If I omit the call to SCM_CDRLOC, do I risk introducing
> Heisenbug segmentation faults?

No.  Garbage protection here does not work through tail (though I have
no idea how the Boehm GC would treat it) but through lst.

> More generally, how does this all work? I see that when
> one has an SCM at hand, one has to start caring about
> GC when storing it in members (such as in engravers).
> For example, if I were the author of the below code, how
> would I understand that the mmrest_event_ should be
> unprotected?
>
> void
> Part_combine_iterator::kill_mmrest (Context *c)
> {
>   if (!mmrest_event_)
>     {
>       mmrest_event_ = new Stream_event
>       (Lily::ly_make_event_class (ly_symbol2scm 
> ("multi-measure-rest-event")));
>       set_property (mmrest_event_, "duration", SCM_EOL);
>       mmrest_event_->unprotect ();
>     }
>
>   c->event_source ()->broadcast (mmrest_event_);
> }

Any Smob created with new is initially protected and needs exactly one
call to unprotect to be subject to garbage protection.  A Simple_smob is
created as an SCM value via smobbed_copy () and is dependent on garbage
protection via this SCM value from the beginning.  No call to unprotect
needed.

Some information may be in lily/include/smobs.hh .

-- 
David Kastrup



reply via email to

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