Here are the source codes of Parallel_reader::available_threads in storage\innobase\row\row0pread.cc. I have some question about it.
size_t Parallel_reader::available_threads(size_t n_required,
bool use_reserved) {
auto max_threads = MAX_THREADS;
constexpr auto SEQ_CST = std::memory_order_seq_cst;
auto active = s_active_threads.fetch_add(n_required, SEQ_CST);
if (use_reserved) {
max_threads += MAX_RESERVED_THREADS;
}
if (active < max_threads) {
const auto available = max_threads - active;
if (n_required <= available) {
return n_required;
} else {
const auto release = n_required - available;
const auto o = s_active_threads.fetch_sub(release, SEQ_CST);
ut_a(o >= release);
return available;
}
}
const auto o = s_active_threads.fetch_sub(n_required, SEQ_CST);
ut_a(o >= n_required);
return 0;
}
After we get that 'n_required' > 'available', we release 'release' threads.
Why we release there? The value of 'available' won't change. As a result, the return is still the old one which doesn't change after the 'release' operation.
size_t Parallel_reader::available_threads(size_t n_required,
bool use_reserved) {
auto max_threads = MAX_THREADS;
constexpr auto SEQ_CST = std::memory_order_seq_cst;
auto active = s_active_threads.fetch_add(n_required, SEQ_CST);
if (use_reserved) {
max_threads += MAX_RESERVED_THREADS;
}
if (active < max_threads) {
const auto available = max_threads - active;
if (n_required <= available) {
return n_required;
} else {
const auto release = n_required - available;
const auto o = s_active_threads.fetch_sub(release, SEQ_CST);
ut_a(o >= release);
return available;
}
}
const auto o = s_active_threads.fetch_sub(n_required, SEQ_CST);
ut_a(o >= n_required);
return 0;
}
After we get that 'n_required' > 'available', we release 'release' threads.
Why we release there? The value of 'available' won't change. As a result, the return is still the old one which doesn't change after the 'release' operation.