diff --git a/new.cc b/new.cc index 58ae447..251ee74 100644 --- a/new.cc +++ b/new.cc @@ -79,3 +79,77 @@ EXPORT void operator delete(void *ptr, size_t size) noexcept { EXPORT void operator delete[](void *ptr, size_t size) noexcept { h_free_sized(ptr, size); } + +#if __cplusplus >= 201703L +COLD static void *handle_out_of_memory(size_t size, size_t alignment, bool nothrow) { + void *ptr = nullptr; + + do { + std::new_handler handler = std::get_new_handler(); + if (handler == nullptr) { + break; + } + + try { + handler(); + } catch (const std::bad_alloc &) { + break; + } + + ptr = h_aligned_alloc(alignment, size); + } while (ptr == nullptr); + + if (ptr == nullptr && !nothrow) { + std::__throw_bad_alloc(); + } + return ptr; +} + +static inline void *new_impl(size_t size, size_t alignment, bool nothrow) { + void *ptr = h_aligned_alloc(alignment, size); + if (likely(ptr != nullptr)) { + return ptr; + } + return handle_out_of_memory(size, alignment, nothrow); +} + +EXPORT void *operator new(size_t size, std::align_val_t alignment) { + return new_impl(size, static_cast(alignment), false); +} + +EXPORT void *operator new[](size_t size, std::align_val_t alignment) { + return new_impl(size, static_cast(alignment), false); +} + +EXPORT void *operator new(size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept { + return new_impl(size, static_cast(alignment), true); +} + +EXPORT void *operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept { + return new_impl(size, static_cast(alignment), true); +} + +EXPORT void operator delete(void *ptr, std::align_val_t) noexcept { + h_free(ptr); +} + +EXPORT void operator delete[](void *ptr, std::align_val_t) noexcept { + h_free(ptr); +} + +EXPORT void operator delete(void *ptr, std::align_val_t, const std::nothrow_t &) noexcept { + h_free(ptr); +} + +EXPORT void operator delete[](void *ptr, std::align_val_t, const std::nothrow_t &) noexcept { + h_free(ptr); +} + +EXPORT void operator delete(void *ptr, size_t size, std::align_val_t) noexcept { + h_free_sized(ptr, size); +} + +EXPORT void operator delete[](void *ptr, size_t size, std::align_val_t) noexcept { + h_free_sized(ptr, size); +} +#endif