It's possible that multiple changes occur in parallel, so we can't rely on receiving them one at a time
even if the callbacks are synchronized. Handling this substantially complicates the logic such that
it's not really worth doing individual insertions and deletions anymore.
This reverts 94d821a4a9affdd5d3a94d188109928a4f27e078 and replaces it with a solution
that is basically the old code except that it properly handles changes to the structure of the list.