Michel Fortin wrote:
On 2009-10-07 17:53:21 -0400, Craig Black <cbl...@ara.com> said:
Yes, recycling is best and I'm considering it. I'm only worried about
the extra cost.
Andrei
No this is a bad idea. Removing the possibility to delete data will
cause serious problems with heap fragmentation in some programs.
Hum, perhaps we need to review more thoroughly how memory allocation
works. As Andrei said himself, we now have all the necessary parts in
the language to reimplement 'new' as a library function.
So let's say we ditch 'new' and 'delete' as keywords. Let's first
replace the keyword 'new' with a static function of the same name in a
class or a struct. It could be implemented this way:
static T new(A...)(A a) {
T t = GC.alloc!T(); // GC.alloc sets the T.init bits.
t.__ctor(a);
return t;
}
Usage:
Foo foo = Foo.new();
That's a static function template that needs to be reimplemented for
every subclass (Andrei already proposed such kind of mixins) and that
returns a garbage-collected object reference. Now, if you want manual
allocation:
static T new(A...)(A a) {
T t = GC.allocNoCollect!T(); // GC won't collect this bit.
t.__ctor(a);
return t;
}
void dispose() {
this.__dtor();
GC.free(this);
}
Usage:
Foo foo = Foo.new();
...
foo.dispose();
But then you could do much better: 'new' could return a different type:
a smart reference-counted pointer struct for instance. The possibilities
are endless.
Prior to this post I'd been on the side of retaining "good ole" delete, owing somewhat to
my own tendency to do Evil Things with overloaded new/delete, such as transparent
free-lists.
I've become neutral in light of the above proposed technique, because it really doesn't
break that kind of usage. In fact, it technically makes it more reliable and more
flexible since the behavior of these is more predictable (not subject to compiler
quality/method-of-implementation, and guaranteed to be "just another function").
That said, the stdlib (or probably druntime) needs to provide good general-case support
for this, which should include some sort of IDisposable interface (as mentioned repeatedly
by others) otherwise we're jumping into the abyss (of massive repetitive coding) rather
than over it (into the Elysian fields).
One consideration is that new(), perhaps, ought not be a static member of its class at
all, but rather a global written along similar lines to tools such as "to". Given that,
one could write something like:
##################################################
class C {...}
C new (T:C, A...) (A a) {
auto c = GC.alloc!T();
c.__ctor(a);
return c;
}
auto somevar = new! C (1, 2, 3);
// free-listed
class F {...}
F new (T:F, A...) (A a) {
return F.List.length != 0
? F.List.pop
: defaultNew! F (a)
;
}
##################################################
The latter examples shows my thinking: that the stdlib/druntime could easily provide a
default new() that does what the current new operator does. Class designers could then
overload this default new() as needed. Provide a reasonable alias for the standard new()
(I used "defaultNew" above, but its probably not the best) and it can still be used as
backup in custom functions, such as in the free-list example.
Incidentally... does anyone else notice that, in the static-new proposal, we've once again
recreated Ruby?
Proposed D2:
auto foo = Foo.new;
Ruby:
foo = Foo.new
At least mine looks more like current syntax:
auto foo = new! Foo;
-- Christopher Nicholson-Sauls