When we have an object acting as resource guard for memory, we can convert
it into a deleter using
make_deleter([obj = std::move(obj)] {})
introduce a simpler interface
make_object_deleter(std::move(obj))
for doing the same thing.
While make_free_deleter(nullptr) will function correctly,
deleter::operator bool() on the result will not.
Fix by checking for null, and avoiding the free deleter optimization in
that case -- it doesn't help anyway.
In many cases, a deleter is used to protect raw memory (e.g. a char array,
not something with a destructor). In that case we can simply free() it,
so, the deleter need not remember which destructor needs to be called.
It does need to remember whether it's a raw object or not, so we take over
the least significant bit and use it as a marker, and store the pointer
to the object in the deleter, instead of using a proxy impl object to
control actual deletion.
If the deleter is subsequently share()d, we have to convert it back to
the standard form, since the reference count lives in the impl object.
Move reference counting into the deleter core, instead of relegating it
to a shared_deleter (which has to be allocated) and an external reference
counted (also allocated). This dramatically reduces dynamic allocations.
deleter::share() is causing massive amounts of allocation. First,
since usually a packet's deleter is not a shared_deleter, we need to
allocate that shared_deleter. Second, we need an external reference
count which requires yet another allocation.
Making reference counting part of the deleter class would solve both of
these problems, but we cannot easily do that, since users hold
std::unique_ptr<deleter> which is clearly not sharable.
We could do a massive s/unique_ptr/shared_ptr/ here, but that would have
the side effect of making sharing "too easy" - you simply copy the pointer.
We'd like to keep it explicit.
So to make the change easier, rename the existing unique_ptr<deleter> as
plain "deleter", whereas the old "deleter" becomes deleter::impl:
old name new name
-------- --------
deleter deleter::impl
unique_ptr<deleter> deleter
with exactly the same semantics. A later patch can then add explicit sharing.