[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