Pass continuations for success and failure cases (#788)
This PR provides a templated parameter to the allocation routines. This can be used to add special behaviour in both the successful allocation behaviour, and in the failing to allocate cases. The intent of this is two enable two future features * set_new_handler - so that the failure case doesn't just set ENOMEM, and return nullptr. But can handle both the Windows and C++ versions of (_)set_new_handler. * The success handler can be used to add checking, zeroing and in the future storing precise size information in metadata for each allocation.
This commit is contained in:
committed by
GitHub
parent
012138e29f
commit
d4c7e01cd7
@@ -91,7 +91,7 @@ int main()
|
||||
{
|
||||
static const size_t sz = 1024 * 1024;
|
||||
errno = 0;
|
||||
void* olarge = alloc->alloc<YesZero>(sz);
|
||||
void* olarge = alloc->alloc<Zero>(sz);
|
||||
int err = errno;
|
||||
|
||||
SNMALLOC_CHECK(alarge == address_cast(olarge));
|
||||
|
||||
@@ -47,14 +47,14 @@ void check_calloc(void* p, size_t size)
|
||||
|
||||
void calloc1(size_t size)
|
||||
{
|
||||
void* r = snmalloc::alloc<snmalloc::ZeroMem::YesZero>(size);
|
||||
void* r = snmalloc::alloc<snmalloc::Zero>(size);
|
||||
check_calloc(r, size);
|
||||
snmalloc::dealloc(r);
|
||||
}
|
||||
|
||||
void calloc2(size_t size)
|
||||
{
|
||||
void* r = snmalloc::alloc<snmalloc::ZeroMem::YesZero>(size);
|
||||
void* r = snmalloc::alloc<snmalloc::Zero>(size);
|
||||
check_calloc(r, size);
|
||||
snmalloc::dealloc(r, size);
|
||||
}
|
||||
|
||||
@@ -173,10 +173,12 @@ namespace
|
||||
size * 2);
|
||||
EXPECT(
|
||||
ptr[size] == 0,
|
||||
"Memory not zero initialised for {} byte reallocation from {} "
|
||||
"Memory not zero initialised for {} byte reallocation from {} with "
|
||||
"align {}"
|
||||
"byte allocation",
|
||||
size * 2,
|
||||
size);
|
||||
size,
|
||||
align);
|
||||
// The second time we run this test, we if we're allocating from a free
|
||||
// list then we will reuse this, so make sure it requires explicit
|
||||
// zeroing.
|
||||
|
||||
@@ -178,7 +178,7 @@ void test_calloc()
|
||||
memset(p, 0xFF, size);
|
||||
snmalloc::dealloc(p, size);
|
||||
|
||||
p = snmalloc::alloc<YesZero>(size);
|
||||
p = snmalloc::alloc<Zero>(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
@@ -417,7 +417,7 @@ void test_calloc_16M()
|
||||
// sizes >= 16M use large_alloc
|
||||
const size_t size = 16'000'000;
|
||||
|
||||
void* p1 = snmalloc::alloc<YesZero>(size);
|
||||
void* p1 = snmalloc::alloc<Zero>(size);
|
||||
SNMALLOC_CHECK(snmalloc::alloc_size(snmalloc::external_pointer(p1)) >= size);
|
||||
snmalloc::dealloc(p1);
|
||||
}
|
||||
@@ -430,7 +430,7 @@ void test_calloc_large_bug()
|
||||
// not a multiple of page size.
|
||||
const size_t size = (MAX_SMALL_SIZECLASS_SIZE << 3) - 7;
|
||||
|
||||
void* p1 = snmalloc::alloc<YesZero>(size);
|
||||
void* p1 = snmalloc::alloc<Zero>(size);
|
||||
SNMALLOC_CHECK(snmalloc::alloc_size(snmalloc::external_pointer(p1)) >= size);
|
||||
snmalloc::dealloc(p1);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ void check_calloc(void* p, size_t size)
|
||||
void calloc1(size_t size)
|
||||
{
|
||||
trigger_teardown();
|
||||
void* r = snmalloc::alloc<snmalloc::ZeroMem::YesZero>(size);
|
||||
void* r = snmalloc::alloc<snmalloc::Zero>(size);
|
||||
check_calloc(r, size);
|
||||
snmalloc::dealloc(r);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void calloc1(size_t size)
|
||||
void calloc2(size_t size)
|
||||
{
|
||||
trigger_teardown();
|
||||
void* r = snmalloc::alloc<snmalloc::ZeroMem::YesZero>(size);
|
||||
void* r = snmalloc::alloc<snmalloc::Zero>(size);
|
||||
check_calloc(r, size);
|
||||
snmalloc::dealloc(r, size);
|
||||
}
|
||||
|
||||
@@ -5,20 +5,21 @@
|
||||
|
||||
using namespace snmalloc;
|
||||
|
||||
template<ZeroMem zero_mem>
|
||||
template<typename Conts>
|
||||
void test_alloc_dealloc(size_t count, size_t size, bool write)
|
||||
{
|
||||
{
|
||||
MeasureTime m;
|
||||
m << "Count: " << std::setw(6) << count << ", Size: " << std::setw(6)
|
||||
<< size << ", ZeroMem: " << (zero_mem == YesZero) << ", Write: " << write;
|
||||
<< size
|
||||
<< ", ZeroMem: " << std::is_same_v<Conts, Zero> << ", Write: " << write;
|
||||
|
||||
std::unordered_set<void*> set;
|
||||
|
||||
// alloc 1.5x objects
|
||||
for (size_t i = 0; i < ((count * 3) / 2); i++)
|
||||
{
|
||||
void* p = snmalloc::alloc<zero_mem>(size);
|
||||
void* p = snmalloc::alloc<Conts>(size);
|
||||
SNMALLOC_CHECK(set.find(p) == set.end());
|
||||
|
||||
if (write)
|
||||
@@ -40,7 +41,7 @@ void test_alloc_dealloc(size_t count, size_t size, bool write)
|
||||
// alloc 1x objects
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
void* p = snmalloc::alloc<zero_mem>(size);
|
||||
void* p = snmalloc::alloc<Conts>(size);
|
||||
SNMALLOC_CHECK(set.find(p) == set.end());
|
||||
|
||||
if (write)
|
||||
@@ -67,18 +68,18 @@ int main(int, char**)
|
||||
|
||||
for (size_t size = 16; size <= 128; size <<= 1)
|
||||
{
|
||||
test_alloc_dealloc<NoZero>(1 << 15, size, false);
|
||||
test_alloc_dealloc<NoZero>(1 << 15, size, true);
|
||||
test_alloc_dealloc<YesZero>(1 << 15, size, false);
|
||||
test_alloc_dealloc<YesZero>(1 << 15, size, true);
|
||||
test_alloc_dealloc<Uninit>(1 << 15, size, false);
|
||||
test_alloc_dealloc<Uninit>(1 << 15, size, true);
|
||||
test_alloc_dealloc<Zero>(1 << 15, size, false);
|
||||
test_alloc_dealloc<Zero>(1 << 15, size, true);
|
||||
}
|
||||
|
||||
for (size_t size = 1 << 12; size <= 1 << 17; size <<= 1)
|
||||
{
|
||||
test_alloc_dealloc<NoZero>(1 << 10, size, false);
|
||||
test_alloc_dealloc<NoZero>(1 << 10, size, true);
|
||||
test_alloc_dealloc<YesZero>(1 << 10, size, false);
|
||||
test_alloc_dealloc<YesZero>(1 << 10, size, true);
|
||||
test_alloc_dealloc<Uninit>(1 << 10, size, false);
|
||||
test_alloc_dealloc<Uninit>(1 << 10, size, true);
|
||||
test_alloc_dealloc<Zero>(1 << 10, size, false);
|
||||
test_alloc_dealloc<Zero>(1 << 10, size, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user