lilypond-devel
[Top][All Lists]
Advanced

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

Re: C++ question on wrapper API for setting Guile fluids


From: Jean Abou Samra
Subject: Re: C++ question on wrapper API for setting Guile fluids
Date: Thu, 21 Apr 2022 13:00:34 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0

Le 21/04/2022 à 11:18, Han-Wen Nienhuys a écrit :
OK. I'm curious to see how that turns out.


I am too :-)

I've been intermittently working on this project for more than
6 months now. When I do an experimental refactoring, I make
a new branch from the current one to avoid losing the previous work.
Currently I am working in a branch called 'purity5' ...


Does every call to
get_property() will have to check the fluid as well to see if it
should cache the computed value?



Yes. I'm trying to make it such that this check is fast, because
get_property without purity at all is the frequent case.


How does the caching framework know if the computation depends on the
assumption?



In my current design, Output_def gains a new member, which is a
stack (SCM list). Each element of the stack corresponds to a
property callback that is currently being made. The element is
a list of assumptions that have been used for this call. Suppose,
for example, that you have the call chain

VerticalAxisGroup.adjacent-pure-heights
[introduces *prebreak-estimate*, *prebreak-estimate-start*, *prebreak-estimate-end*]
-> PaperColumn.Y-extent
-> NoteColumn.Y-extent
-> Stem.Y-extent

Each get_property call pushes a frame on the Output_def's stack.
During the Stem.Y-extent callback, the stack looks like

(() ;; Stem.Y-extent
 () ;; NoteColumn.Y-extent
 () ;; PaperColumn.Y-extent
 () ;; VerticalAxisGroup.adjacent-pure-heights
 ...)


Moreover, when the *prebreak-estimate* assumption is introduced,
it records the state of the stack. So *prebreak-estimate* remembers
the SCM sublist that corresponds to the part

(() ;; VerticalAxisGroup.adjacent-pure-heights
 ...)

(Equivalently, it could also remember the stack's depth.)

Now, Stem.Y-extent accesses *prebreak-estimate*. This records
in the stack that callbacks inside the scope where the assumption
has been introduced need to get special caching. More precisely,
the stack is walked until the sublist recorded by
*prebreak-estimate* is found. This makes it look like


((#<Assumption [*prebreak-estimate*]>) ;; Stem.Y-extent
 (#<Assumption [*prebreak-estimate*]>) ;; NoteColumn.Y-extent
 (#<Assumption [*prebreak-estimate*]>) ;; PaperColumn.Y-extent
 () ;; VerticalAxisGroup.adjacent-pure-heights
 ...)


At the end of the Stem.Y-extent get_property () call,
the top frame is popped off and checked. If it's '(), the
property can be cached normally. If it's a 1-element list
containing *prebreak-estimate*, it receives caching with
a prebreak value and a postbreak value. Anything else
leads to no caching at all. (Except if benchmarks tell that
it brings a performance advantage to cache according to
(start, end) in a hash table.)





reply via email to

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