Don't do this. Use a condition_variable instead. This will require some minor revising. 50ms might be a long time. Remember that to the OS, it means "context switch out the thread and keep it idle for at least 50ms". A std::mutex may have all manner of fancy implementation dependent optimizations. ...
Avoid mixing clock types
Why use std::chrono::_V2::system_clock::time_point start but initialize it with std::chrono::high_resolution_clock::now()? If there is a reason to use the non-standard _V2 clocks, then you should probably stick with it everywhere. But if there is no reason to, avoid the non-standard _V2 thing.
To make your code more consistent and ...
I get a couple of warnings, which ought to be fixed:
g++ -std=c++2a -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Weffc++ -pthread 235651.cpp -o 235651
235651.cpp: In constructor ‘Buffer::Buffer()’:
235651.cpp:31:5: warning: ‘Buffer::mu’ should be initialized in the member initialization list [-Weffc++]
31 | ...
C++ port of Björn's code using a single large array instead of one hashmap per thread. Björn's C code is very nice, but this question was tagged C++ so i thought it was worth showing that too. The changes from my code above are very small:
Using std::thread instead of std::async, because we don't need to return anything
Use a std::unique_ptr of std::atomic&...
I hope you don't mind a pure C solution. For me it is easier to
optimize code without C++ abstractions. But it should be
straightforward to convert it to idiomatic C++ code.
I don't think there is actually a need for two channel. Whether the sub-slice is from the left part or the right part does not matter when you merge, you can simply use a single channel.
MS := make(chan byte)
go mergeSort(arr[:len(arr)/2], MS)
go mergeSort(arr[len(arr)/2:], MS)
left, right := <-MS, <-MS
This is better because it avoids potential ...