So the "best" solution would be:
1. Run metrics computation & null painter as a single non-interruptable, non-reentrant step
(There should be some assertions in the code that check that update isn't executed twice simultaneously; this should be easily doable by the introduction of a static variable that is incremented when entering update and decrement when leaving update)
There already is such an assert. It is based on a bool, not a counter. There was a patch to change it to a counter, but I think that is wrong. The first time, we detect a reentrancy, we have the problem, and it should be fixed.
2. At the end of metrics computation & null painter, check whether there is a new event
3a. If yes, process the event, skip real painting
3b. If no, go on with real painting
Since real painting is suppressed if the user edits text very fast, this solution should be more efficient than the current one.
Yes, something like this should work better. This can be done in steps:
First, just leave the excessive painting as it is, but fix the re-entrancy problem. Then, as a second step, introduce the null-painter as an optimisation for the cases where two sequentive updates are coming right after each other, such as fast typing, which allows us to skip the first paint job.
The third step could be to build something like the update fingerprinting data-structure, as described earlier, which will help painting only what needs to be painted, and also help mitigate any excessive update calls there might be.
In parallel to this, all excessive update calls should be hunted down, and killed without mercy.
Regards, Asger