Thread overview
Scoped Class Instance
Jan 31, 2012
Zachary Lund
Jan 31, 2012
Nicolas Silva
Jan 31, 2012
Trass3r
Jan 31, 2012
Zachary Lund
Jan 31, 2012
Simen Kjærås
January 31, 2012
I've been looking into (basic) memory management within D. Through IRC conversation and reading the article on memory management on dlang.org (which seems to be a bit out-of-date), I've concluded that using a global (or static member) function and emplace() in std.conv is a simple solution for providing alternative allocation methods. However, I cannot, by default, scope my custom allocations. Take this for instance:

void main() {
	MyClass inst = alloc!(MyClass)();
	inst.do_something();
	dealloc(inst);
}

Now, I want my dealloc function to be called automagically. One safe measure is:

void main() {
	MyClass inst = alloc!(MyClass)();
	scope(exit) dealloc(inst);
	inst.do_something();
}

But I'm lazy and I'm looking for shorter methods.

void main() {
	mixin AutoRef(MyClass, "inst");
	inst.do_something();
}

Any ideas?
January 31, 2012
You can use structs for this kind of problems, somethin like

struct Scoped(T)
{
    ~this()
    {
        //handle deallocation here
    }
    T inst;
}

if you create a Scoped!MyClass in a scope, the struct's destructor will be invoked whenever the program leaves the scope, even if it is because of an exception.

On Tue, Jan 31, 2012 at 2:40 PM, Zachary Lund <admin@computerquip.com> wrote:
> I've been looking into (basic) memory management within D. Through IRC conversation and reading the article on memory management on dlang.org (which seems to be a bit out-of-date), I've concluded that using a global (or static member) function and emplace() in std.conv is a simple solution for providing alternative allocation methods. However, I cannot, by default, scope my custom allocations. Take this for instance:
>
> void main() {
>        MyClass inst = alloc!(MyClass)();
>        inst.do_something();
>        dealloc(inst);
> }
>
> Now, I want my dealloc function to be called automagically. One safe measure is:
>
> void main() {
>        MyClass inst = alloc!(MyClass)();
>        scope(exit) dealloc(inst);
>        inst.do_something();
> }
>
> But I'm lazy and I'm looking for shorter methods.
>
> void main() {
>        mixin AutoRef(MyClass, "inst");
>        inst.do_something();
> }
>
> Any ideas?
January 31, 2012
> However, I cannot, by default, scope my custom allocations.
> Any ideas?

std.typecons.scoped
January 31, 2012
On Tuesday, 31 January 2012 at 15:19:00 UTC, Trass3r wrote:
>> However, I cannot, by default, scope my custom allocations.
>> Any ideas?
>
> std.typecons.scoped

I looked into this and I'm unsure of its exact use. It says, "Allocates a class object right inside the current scope" which doesn't really define how it's allocated nor does it explain how this would work with custom de/allocators. Also, it claims it "avoids" the overhead of new of which I'm not entirely sure of what it means. Could some clarification be made?
January 31, 2012
On Tue, 31 Jan 2012 16:42:52 +0100, Zachary Lund <admin@computerquip.com> wrote:

> On Tuesday, 31 January 2012 at 15:19:00 UTC, Trass3r wrote:
>>> However, I cannot, by default, scope my custom allocations.
>>> Any ideas?
>>
>> std.typecons.scoped
>
> I looked into this and I'm unsure of its exact use. It says, "Allocates a class object right inside the current scope" which doesn't really define how it's allocated nor does it explain how this would work with custom de/allocators. Also, it claims it "avoids" the overhead of new of which I'm not entirely sure of what it means. Could some clarification be made?

If scoped is used inside a struct or class, it allocates the space within
that struct or class. If used inside a function, the space is allocated
on the stack. The size of the allocated buffer must be known at compile
time, so you may not put an instance of a subclass into a scoped variable.

Because the class may be allocated on the stack, returning it from a
function is a Bad Idea™, unless it's part of a struct or class you know
will survive for a while longer.

The reason it avoids the overhead of new is it does not allocate using
new. Basically, Scoped does this:

class A {}

A scoped = cast(A)alloca(sizeof(A));
A.__ctor(args);