Based on our internal discussions we decided to change our direction with XPC support for clangd. We did some extra measurements and found out that JSON serialized over XPC is good enough for our use-case. We also took into consideration that we'd have to deal with support for multiple workspaces in near future.
Probably the simplest solution is to keep XPC completely out of clangd binary and use one clangd instance per workspace. This design means it's the least intrusive change, it's rather simple (compared to adding support for multiple workspaces to clangd itself) and robust (compared to threads-based implementation). Long-term it's hopefully also going to be less maintenance-demanding since it's dependent only on LSP and not it's implementation.
The patch is nearly finished - I just wanted to get some feedback on the design early on (before finishing doxygen annotations, documentation, etc.).
Our approach to testing for the future is to reuse existing clangd lit tests and just send messages through our XPC code. For the time being there's just a single minimal testcase.