January 27, 2015
On Saturday, 24 January 2015 at 23:28:35 UTC, Jerry Morrison wrote:
> On Saturday, 24 January 2015 at 15:04:47 UTC, Ola Fosheim Grøstad wrote:
>> If the classes are written for RAII then the destructors have to be called in reverse order of the constructors. IIRC D does not guarantee this when you use the GC.
>>
>> So to do it right there is a lot of GC overhead.
>
> Yes, but the usability question is what do programmers expect? How much do they assume before turning to the docs?

Unfortunately, I think D is now entrenched in Java/C#ish expectations. Which is no good, since the main advantage D can have over those languages is to restrict the language semantics to a level where D has an inherent performance (timeliness) advantage.

My expectations from a GC in a system level programming language would be to give max priority to fast collection at the expense of features (lean and mean).

> It's a big stretch to expect LIFO behavior from garbage collection. It's not a stretch to expect logging to work.

What does logging in a destructor tell you? The destructor might not execute until the program terminates.

You might not expect LIFO from the GC, but can you trust library authors to ensure that it does assume LIFO when manual memory management becomes commonplace?

D needs to define what it means by "safe" and "convenient". It is currently very much up in there air when it applies and when it does not.

January 28, 2015
On Tuesday, 27 January 2015 at 22:46:30 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 24 January 2015 at 23:28:35 UTC, Jerry Morrison wrote:
>> On Saturday, 24 January 2015 at 15:04:47 UTC, Ola Fosheim Grøstad wrote:
>>> If the classes are written for RAII then the destructors have to be called in reverse order of the constructors. IIRC D does not guarantee this when you use the GC.
>>>
>>> So to do it right there is a lot of GC overhead.
>>
>> Yes, but the usability question is what do programmers expect? How much do they assume before turning to the docs?
>
> Unfortunately, I think D is now entrenched in Java/C#ish expectations. Which is no good, since the main advantage D can have over those languages is to restrict the language semantics to a level where D has an inherent performance (timeliness) advantage.
>
> My expectations from a GC in a system level programming language would be to give max priority to fast collection at the expense of features (lean and mean).
>
>> It's a big stretch to expect LIFO behavior from garbage collection. It's not a stretch to expect logging to work.
>
> What does logging in a destructor tell you? The destructor might not execute until the program terminates.

Logging might help with debugging, say, to log accumulated data before the object disappears. Perhaps it's not a great example, but since logging doesn't do anything dubious like forging a strong link to the object, it would seem safe at first expectation.

Because of this unknown delay before GC collection, also because GC can collect a cycle of objects, we know it can't promise LIFO order.

> You might not expect LIFO from the GC, but can you trust library authors to ensure that it does assume LIFO when manual memory management becomes commonplace?

Sorry, I don't understand the question. I expect LIFO for freeing structs on the stack.

> D needs to define what it means by "safe" and "convenient". It is currently very much up in there air when it applies and when it does not.

Yes.

The forum discussion http://forum.dlang.org/thread/gvaacvczsrybguddoogq@forum.dlang.org?page=1 deals with an InvalidMemoryOperationError. Vladimir Panteleev created a wiki page http://wiki.dlang.org/InvalidMemoryOperationError on how to debug such cases, starting with building a patched Druntime. Very helpful, but not easy.

==> It would be a big step forwards if the runtime printed a clear error message like: "Attempt to allocate GC memory within the destructor for class Foo."
January 28, 2015
From the forum thread http://forum.dlang.org/thread/ossuvfmqthllgdpgzntm@forum.dlang.org?page=1

and the PR https://github.com/D-Programming-Language/dlang.org/pull/851

I learned that allocation in a destructor isn't the only crash case here.

The GC calls a class instance's invariant() method during a collection cycle, before calling the object's destructor, and possibly after destructing objects it references. So if the invariant() touches any of its member references, it can crash!

A solution to that would be to never call invariants during a collection cycle, but what other gotcha's exist during collection? Would @nogc on class destructors help them?
January 28, 2015
On 1/27/15 7:00 PM, Jerry Morrison wrote:
> A solution to that would be to never call invariants during a collection
> cycle, but what other gotcha's exist during collection? Would @nogc on
> class destructors help them?

I, too, think no invariants should be called during GC-triggered destruction.

Andrei

P.S. Good to see you around here, Jerry!
January 28, 2015
On Wednesday, 28 January 2015 at 02:33:11 UTC, Jerry Morrison wrote:
> Sorry, I don't understand the question. I expect LIFO for freeing structs on the stack.

Yes, but if the class is designed for unique_ptr style usage...

Anyway, a destructor is the "END" for the constructor "BEGIN". Together they form a scope. The children of the scope ought to live until the "END". The background for constructor/destructor is that they match a closure. Simula had the INNER keyword so that you could write:

CLASS Transaction BEGIN
   ...open...
   INNER
   ...close...
END

Then specialize it by prefix style subclassing:

Transaction BEGIN
  ...do stuff executed in the inner clause...
END

C++ offer similar semantics with constructor/destructor RAII...

Some languages keep track of parent-child relationships, you can do it in the typing even. Nevertheless, children ought to be alive when the parent dies... If the language cannot provide this, then provide another mechanism such as "finalize" or just disallow GC allocating destructor based classes.

Mish-mashing established programming concepts is Not a Good Idea. :)
January 28, 2015
On Wednesday, 28 January 2015 at 09:51:09 UTC, Ola Fosheim Grøstad wrote:
> Some languages keep track of parent-child relationships, you can do it in the typing even. Nevertheless, children ought to be alive when the parent dies... If the language cannot provide this, then provide another mechanism such as "finalize" or just disallow GC allocating destructor based classes.
>
> Mish-mashing established programming concepts is Not a Good Idea. :)

But wouldn't enforcing strict parent-child relationships make cyclic references illegal ?
January 28, 2015
On Wednesday, 28 January 2015 at 10:36:11 UTC, Matthias Bentrup wrote:
> But wouldn't enforcing strict parent-child relationships make cyclic references illegal ?

You would either need:

- serial number/timestamping (just a sort is required)

- dynamic information like a back pointer

- static typing like an ownership reference type

- behavioural typing (e.g. proper child references are inferred by looking at what is done in the constructor)

But I think GC and destructors are not a good match... so I would personally go for performance and no destructors.

But unions also have to be turned into strongly typed constructs for GC allocation if they can contain reference scanned memory. Behavioural typing could go a long way.
January 30, 2015
On Wednesday, 28 January 2015 at 11:32:26 UTC, Ola Fosheim Grøstad wrote:
> But I think GC and destructors are not a good match... so I would personally go for performance and no destructors.

Yes. That is the bottom line.

A good match for GC is the phantom reference, which notifies you when an object gets collected with no way to resurrect the collected object or access its instance variables.
January 30, 2015
On Friday, 30 January 2015 at 00:28:18 UTC, Jerry Morrison wrote:
> On Wednesday, 28 January 2015 at 11:32:26 UTC, Ola Fosheim Grøstad wrote:
>> But I think GC and destructors are not a good match... so I would personally go for performance and no destructors.
>
> Yes. That is the bottom line.
>
> A good match for GC is the phantom reference, which notifies you when an object gets collected with no way to resurrect the collected object or access its instance variables.

That is more important than the nogc thing, as it has real impact of definition and implementation.

This is the kind of thing we can solve with proper lifetime definition.
1 2 3 4 5 6 7 8 9
Next ›   Last »