server-skynet-source-3rd-je.../src/jemalloc_cpp.cpp
Dave Watson 2319152d9f jemalloc cpp new/delete bindings
Adds cpp bindings for jemalloc, along with necessary autoconf settings.
This is mostly to add sized deallocation support, which can't be added
from C directly.  Sized deallocation is ~10% microbench improvement.

* Import ax_cxx_compile_stdcxx.m4 from the autoconf repo, seems like the
  easiest way to get c++14 detection.
* Adds various other changes, like CXXFLAGS, to configure.ac.
* Adds new rules to Makefile.in for src/jemalloc-cpp.cpp, and a basic
  unittest.
* Both new and delete are overridden, to ensure jemalloc is used for
  both.
* TODO future enhancement of avoiding extra PLT thunks for new and
  delete - sdallocx and malloc are publicly exported jemalloc symbols,
  using an alias would link them directly.  Unfortunately, was having
  trouble getting it to play nice with jemalloc's namespace support.

Testing:
Tested gcc 4.8, gcc 5, gcc 5.2, clang 4.0.  Only gcc >= 5 has sized
deallocation support, verified that the rest build correctly.

Tested mac osx and Centos.

Tested --with-jemalloc-prefix and --without-export.

This resolves #202.
2016-12-12 18:36:06 -08:00

141 lines
2.6 KiB
C++

#include <mutex>
#include <new>
#define JEMALLOC_CPP_CPP_
#include "jemalloc/internal/jemalloc_internal.h"
// All operators in this file are exported.
// Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
// thunk?
//
// extern __typeof (sdallocx) sdallocx_int
// __attribute ((alias ("sdallocx"),
// visibility ("hidden")));
//
// ... but it needs to work with jemalloc namespaces.
void *operator new(std::size_t size);
void *operator new[](std::size_t size);
void *operator new(std::size_t size, const std::nothrow_t&) noexcept;
void *operator new[](std::size_t size, const std::nothrow_t&) noexcept;
void operator delete(void* ptr) noexcept;
void operator delete[](void* ptr) noexcept;
void operator delete(void* ptr, const std::nothrow_t&) noexcept;
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;
#if __cpp_sized_deallocation >= 201309
/* C++14's sized-delete operators. */
void operator delete(void* ptr, std::size_t size) noexcept;
void operator delete[](void* ptr, std::size_t size) noexcept;
#endif
template <bool IsNoExcept>
JEMALLOC_INLINE
void *
newImpl(std::size_t size) noexcept(IsNoExcept)
{
void* ptr = je_malloc(size);
if (likely(ptr != nullptr))
return (ptr);
while (ptr == nullptr) {
std::new_handler handler;
// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
{
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
handler = std::set_new_handler(nullptr);
std::set_new_handler(handler);
}
if (handler == nullptr)
break;
try {
handler();
} catch (const std::bad_alloc&) {
break;
}
ptr = je_malloc(size);
}
if (ptr == nullptr && !IsNoExcept)
std::__throw_bad_alloc();
return (ptr);
}
void *
operator new(std::size_t size)
{
return (newImpl<false>(size));
}
void *
operator new[](std::size_t size)
{
return (newImpl<false>(size));
}
void *
operator new(std::size_t size, const std::nothrow_t&) noexcept
{
return (newImpl<true>(size));
}
void *
operator new[](std::size_t size, const std::nothrow_t&) noexcept
{
return (newImpl<true>(size));
}
void
operator delete(void* ptr) noexcept
{
je_free(ptr);
}
void
operator delete[](void* ptr) noexcept
{
je_free(ptr);
}
void
operator delete(void* ptr, const std::nothrow_t&) noexcept
{
je_free(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept
{
je_free(ptr);
}
#if __cpp_sized_deallocation >= 201309
void
operator delete(void* ptr, std::size_t size) noexcept
{
je_sdallocx(ptr, size, /*flags=*/0);
}
void operator delete[](void* ptr, std::size_t size) noexcept
{
je_sdallocx(ptr, size, /*flags=*/0);
}
#endif // __cpp_sized_deallocation