https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118030
--- Comment #2 from Nathan Myers <ncm at gcc dot gnu.org> ---
Recording here a possible implementation that reliably detects
whether the user has substituted their own ::operator new, so
if not it can use a substitute that does more:
std::atomic<int> ::__op_new_state{0};
template <typename T>
auto std::allocator<T>::allocate_at_least(size_t n)
-> allocation_result<pointer>
{
auto state = __op_new_state.load(memory_order_relaxed);
if (state > 0)
return _M_allocate_at_least(n);
else if (state < 0)
return { ::operator new(__n * sizeof(_Tp)), n };
::operator delete(::operator new(0)); // sample it
if (__op_new_state.load(memory_order_relaxed) == 0) // still?
__op_new_state.store(-1, memory_order_relaxed);
return allocate_at_least(n);
}
void* ::operator new(std::size_t n)
{
if (n == 0 && ::__op_new_state.load(std::memory_order_relaxed) == 0)
::__op_new_state.store(1, std::memory_order_relaxed);
...
}
Relaxed semantics is safe here because all writers would write
the same value.