On Wednesday, 13 July 2016 at 22:42:36 UTC, Adam Sansier wrote:
On Wednesday, 13 July 2016 at 21:27:16 UTC, Lodovico Giaretta
wrote:
At the end, all memory comes from one of these: GC heap,
malloc, mmap, sbrk. All other allocators build on top of these
(or on top of user supplied buffers, which come from these as
well). What those "wrapper" allocators do is managing the
given memory, either using different allocations strategies
for different allocation sizes, or keeping lists of free
blocks instead of returning them using "free", or other things
(have a look at the docs). So at the end they do what you
would manually do in C/C++ to "personalize" the allocations,
with the aim of reducing waste and/or being faster. They are
also arbitrarily composable on top of each other.
I don't know how Phobos will handle exceptions. Maybe use
reference counting (coming soon in D, maybe)? Maybe algorithms
that already have to allocate will switch from using the GC to
using a user-supplied custom allocator, and will use it for
exceptions too.
Currently I'm working on a replacement for std.xml and I'm
making every component take a template parameter to specify
the allocator. Initially the allocators look like a real mess,
but after a couple of days playing with them, you start
understanding the mechanics and at the end you really enjoy
them. Changing a single parameters allows to switch between
@safe gc code and @nogc code in the unittests, without
changing the implementation.
Ok. Is there a way to bundle allocations so that one free will
work?
For example, your exception handling looks good but I need to
supply custom messges. If I use sformat I have to create the
array for the buffer to create the message in. This means I
would have to free both the exception and the string. It would
be nice to be able to do this in one go.
Sometimes it's nice to include runtime info in an error message
such as an OS error code.
As you probably saw, sformat still has some problems with @nogc,
because it internally uses std.uft.encode, which may throw a
GC-allocated exception, but this can be solved.
Not all allocators keep track of the memory ranges they allocated
(e.g.: Mallocator). The ones that do (like Region) usually
provide a deallocateAll method. So the idea is that you allocate
all data needed by your exception (string buffers or whatever)
and the exception itself with one of these allocators, and at the
end of a catch you deallocateAll.
Also, could one create a struct or class for the exception so
that it is automatically free'ed at the end of a catch block,
if caught? Probably not without language help?
I don't think it's feasible without language support for
reference counted classes (which may be added sooner or later, as
it has been asked and proposals have been made, and would be very
useful). Also note that you don't want RAII or scope(exit) in
this case but scope(success), as the exception shall not be
deallocated if another one is raised in the catch block, because
in D the second exception does not "overwrite" the first, but is
chained to it, so that an outer catch can see both of them.