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.

Reply via email to