Thanks for the very helpful review, Krzysztof Findeisen. I was not unhappy with the state of this before the review, but I like it a lot better now. One big change you may not have expected: I went ahead and made GlobalState itself thread-safe, moving all of the operations that needed to lock the mutex into instance methods. That cleaned up a ton - while there's a bit of repetition now in that MaskDict has a number of methods that just trivially forward to GlobalState's implementations, it made Lock unnecessary and it naturally resolved a lot of your concerns about the details of the thread-safety logic.
I know you're not around this week, but if you are interested in and able to take another look, I'm not in a hurry to merge this (though I do hope to by the end of the week - I just need to merge it before
DM-15500, which is not done yet).