Eliminate class allocators and deallocators?
Chris Nicholson-Sauls
ibisbasenji at gmail.com
Thu Oct 8 02:00:03 PDT 2009
Michel Fortin wrote:
> On 2009-10-07 17:53:21 -0400, Craig Black <cblack at 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
More information about the Digitalmars-d
mailing list