On Friday, 19 May 2017 at 21:24:51 UTC, Adam D. Ruppe wrote:
"NewExpressions are used to allocate memory on the garbage
collected heap (default) or using a class or struct specific
allocator. "
"If a NewExpression is used as an initializer for a function
local variable with scope storage class, and the ArgumentList
to new is empty, then the instance is allocated on the stack
rather than the heap or using the class specific allocator. "
IMHO, this has to go. Having alignment control now, and with
DIP1000 solving reference escaping, there's absolutely no need in
this special syntax; stack-allocated classes are possible as
library types.
But it may be beneficial to reconsider the 'new (AllocatorOpts)'
syntax, with more thought on interaction with the type system. As
in, it's not necessary to have type-specific allocation
functions. But some sort of type system flag is required if we
want to make the language aware of our allocation schemes. To
expand on my previous reply, something like this comes to mind:
// Delcaring class/struct not supporting being allocated by a
non-@nogc allocator:
class [(nogc)] ClassName [(template parameters)] { ... }
struct [(nogc)] StructName [(template parameters)] { ... }
// Declaring arrays:
T[][(nogc)] arr;
So it could look like this:
class Allocator
{
void[] allocate(size_t, TypeInfo ti = null) @nogc { ... }
void deallocate(void[]) @nogc { ... }
}
Allocator myAllocator = /* however is desired */;
class (nogc) MyClass
{
int[] gcArray;
int[] (nogc) nonGCArray;
// note the ctor itself is not @nogc, since it allocates
// gcArray, so interoperability is possible
this()
{
gcArray = [1, 2]; // fine
nonGCArray = [1, 2]; // error
nonGCArray = new (myAllocator) int[2];
}
~this()
{
myAllocator.dispose(nonGCArray);
}
}
auto a = new MyClass; // error, no allocator provided, GC
assumed, MyClass cannot be allocated by GC
auto b = new (myAllocator) MyClass; // fine
auto c = new (theAllocator) MyClass; // error, theAllocator is
not @nogc
---
Not a very pretty syntax, but I can't think of a way of making it
any prettier...
Bringing this back to exceptions, it should "just work":
class (nogc) NoGCException : Exception { ... }
throw new (myAllocator) Exception("Argh!");
//...
catch (NoGCException e) {
} // error, e is not rethrown or disposed
catch (NoGCException e) {
myAllocator.dispose(e);
} // fine, e was disposed
This, however, means teaching the language a few extra library
constructs. And of course, there's the danger of deallocating
with the wrong allocator, but being careful comes with the
territory as far as memory management is concerned.