Karya, built on Mon Jul 24 11:39:07 PDT 2017 (patch 33511aca01257b76b88de7c7a2763b7a965c084e)

Cmd.Performance

Description

This module manages the performance of music, specifically the creation of performance threads.

Performance is relative to a toplevel block, so each block has its own set of caches. Since performance is lazy, a separate thread will force it asynchronously.

Synopsis

# Documentation

Update the performances by rederiving if necessary. This means figuring out ScoreDamage, and if there has been damage, killing any in-progress derivation and starting derivation for the focused and root blocks. This updates performances for the root block and all visible blocks.

The majority of the calls here will bring neither score damage nor a changed view id, and thus this will do nothing.

This is tricky, and I've gotten it wrong in the past, so here's a detailed description:

Merge ui damage with each perf's damage. Then for each perf, if it's Cmd.state_current_performance has damage, kill its thread, and remove its entry in Cmd.state_performance_threads. The lack of a thread entry, whether because was removed or never existed, means that a block should be rederived. Derivation creates a new Msg.Performance and an evaluate thread, and puts them into Cmd.state_current_performance and Cmd.state_performance_threads respectively, but due to laziness, no actual derivation happens unless someone (like play) happens to look at the performance. This all happens synchronously, so the next time update_performance is called, it sees a nice clean new Performance with no damage.

Meanwhile, the evaluate thread asynchronously waits for a bit, then forces the contents of the Performance, and then sends it back to the responder so it can stash it in Cmd.state_performance. If a new change comes in while it's waiting it'll get killed off, and the out-of-date derivation will never happen. Yay for laziness!

Which blocks should get derived?

Constructor for Msg.Performance.