memory management and the standard library
Sjoerd Nijboer
dlang at sjoerdnijboer.com
Sun Mar 17 14:28:49 UTC 2019
On Saturday, 16 March 2019 at 21:17:02 UTC, Olivier FAURE wrote:
> On Saturday, 16 March 2019 at 20:17:50 UTC, Jacob Carlborg
> wrote:
>> Instead of having a function allocate memory, pass a buffer,
>> delegate, output range or something similar to the function.
>> Then whatever you pass can decide if it should allocate using
>> the GC, malloc or something else.
>
> It would have to be a delegate or an output range, because in
> most cases the callee wouldn't know in advance how much storage
> it needs to allocate.
>
> Anyway, it would be pretty nice if there were a standardized
> way to tell a function how it should allocate its memory; it
> would allow some nice strategies like "I know that I'm going to
> discard most of what this function allocates, so just put in in
> a continuous buffer; then deep-copy the relevant data to GC
> memory, and throw the rest away" (eg in a parser).
>
> However, for that to work, you'd probably need a way to pass
> implicit arguments to a function without having to specify
> `foobar(defaultGcAllocator, x, y, z)` every time you call a
> function.
How about something like the following?
It introduces an overload of keyword new, a keyword 'old' and a
keyword 'lifetime' to pass in an IAllocator as a template
argument to a function, and change the name mangling to add it as
a hidden parameter.
/*MyClass is an implicit template which takes an IAllocator. It
can always be implicitly casted to a MyClass for backwards
compatibility. It can use this allocator using the .allocatorOf
property.*/
class MyClass
{
public MyClass getANEwInstance(MyClass a, MyClass b)
{
.... //some code
return this.allocatorOf new MyClass();
}
/*This function takes Myclass A as a parameter and returns a new
instance of MyClass using thesame allocator. if no explicit
allocator is used for a, or no allocator is known, the default
GC_ALLOCATOR is used. This allows for better compatibility with
existing D libraries.*/
public lifetime(a) getANewInstanceFromParameter(lifetime
MyClass a)
{
.... //some code
return a.allocatorof new MyClass();
}
/* a class which has a lifetime associated with it, should be
able to decay into a "normal" class so they can still be used in
existing codebases. They are an opt-in feature because of it.
simpleProperty() demonstrates this. */
public bool simpleProperty(MyClass myClass)
{
....
return myClass.someProperty();
}
}
//usage:
public void foo(IAllocator A)()
{
MyClass c1 = new MyClass(); //Use default GC allocator.
MyClass c2 = Mallocator new MyClass (); // Allocate using
malloc.
/*Instantiate MyClas using allocator A, and mangle the allocator
A into the
resulting type as the first template parameter.*/
MyClass c3 = A new MyClass();
/* since a reference to a class instance is still a pointer, we
can discard the allocator of the pointer and call regular D, C++
and C functions with it. */
println(c3.simpleProperty());
// get a new object with thesame allocator as c1, since c1 is a
@lifetime object.
auto c4 = c1.getANEwInstance();
auto c5 = c2.getANewInstanceFromParameter(c3);
old c1; // no-operation
old c2; // destruct and free c2
old c3; // destruct and free c3 if A is not a GC allocator
using introspection.
old c4; /*destruct and free using thesame allocator as c1,
meaning no-op in this case.*/
old c5; /*destruct and free using thesame allocator as c3,
meaning this is conditional on A being a GC allocator.*/
}
`
I think that this is an example which would be quite easy to
learn, not a huge strain on the developers, backwards compatible
with existing D code and potentially immensely powerfull. It
would also give helpful info which can be used by debuggers and
other tooling. One thing it can never do is return an object
which was conditionally allocated with one allocator or another.
More information about the Digitalmars-d
mailing list