lilypond-devel
[Top][All Lists]
Advanced

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

Re: Guile GC in C++


From: Jean Abou Samra
Subject: Re: Guile GC in C++
Date: Tue, 6 Jul 2021 16:52:19 +0200 (CEST)

   Le 06/07/2021 10:59, David Kastrup <[1]dak@gnu.org> a écrit :

   Jean Abou Samra <[2]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 .

   Thank you, this helped.

References

   1. mailto:dak@gnu.org
   2. mailto:jean@abou-samra.fr


reply via email to

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