May 03, 2014
Am 03.05.2014 17:20, schrieb "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com>":
> On Saturday, 3 May 2014 at 15:10:43 UTC, Paulo Pinto wrote:
>> Easy, you already know that you don't need the node, just call the
>> dispose method, instead of marking for release.
>
> But you don't know unless you use RC or GC.

I am always speaking from the point of view of automatic memory management, be it RC, GC or compiler aided dataflow analysis.

> Let's say you make a jungle.
> Lots of pointers to the tree root node. And you also don't want to wait
> with collection if you hold onto hardware resources (forcing perhaps
> lower resolution graphics if you are low on GPU resources).


If you mean you need to be sure that all references are gone from the graph, before doing a dispose() invocation, then yeah you need some form of RC, even with a GC.

However that doesn't mean that the developer/API client needs to care about it.

It is a matter of how the graph node construction is exposed to the clients. With proper a proper ADT that can be hidden from the API client.

Automatic resource management requires another type of thinking anyway.

--
Paulo


May 03, 2014
On 5/3/14, 5:39 AM, monnoroch wrote:
>
>> Hey I have this global variable, if I assign a value to it and later
>> null it, it'll call its destructor if its not referenced anywhere else.
>> Which in turn would make me think ref counting would be a good idea.
>
> It seems, that ARC is the only way. There were idea to make all
> non-scoped (in my terminology) objects ARC-d, if they have dtors. That
> makes sense to me.

Interesting, we haven't explored that. The most problematic implication would be that classes with destructors will form a hierarchy separate from Object.

Andrei
May 03, 2014
On Saturday, 3 May 2014 at 18:27:46 UTC, Andrei Alexandrescu wrote:
> On 5/3/14, 5:39 AM, monnoroch wrote:
>>
>>> Hey I have this global variable, if I assign a value to it and later
>>> null it, it'll call its destructor if its not referenced anywhere else.
>>> Which in turn would make me think ref counting would be a good idea.
>>
>> It seems, that ARC is the only way. There were idea to make all
>> non-scoped (in my terminology) objects ARC-d, if they have dtors. That
>> makes sense to me.
>
> Interesting, we haven't explored that. The most problematic implication would be that classes with destructors will form a hierarchy separate from Object.
>
> Andrei

Yeah, that's a good point: How do you define a "class with/without destructor", when they all derive from Object anyways.

Necessarily, Object needs to have a destructor (even if it does nothing) for any other sub-class to have them. Or vice versa, if Object has no destructor, no subclass can have them?

So is it even possible to separate classes into two different groups?
May 03, 2014
> The most problematic implication would be that classes with destructors will form a hierarchy separate from Object.

What for? As i understand object's dtor does nothing, so for any class we can determine, if dtor is empty. I don't see a problem here.
Cycles and locks for RC are the biggest problems, if you ask me.
Also, what about arrays and maps?
May 03, 2014
> Interesting, we haven't explored that. The most problematic implication would be that classes with destructors will form a hierarchy separate from Object.

As i understood, you want to remove dtors for non-scoped objects completely, so all classes will be without it, except user defined ones.
Can we mark all dtors virtual by default, so there wouldn't need to be dtor in object?
May 03, 2014
On 2014-05-03 18:27:47 +0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

> Interesting, we haven't explored that. The most problematic implication would be that classes with destructors will form a hierarchy separate from Object.

Seems like people have been ignoring my two posts in the thread "radical ideas about gc and reference counting". I've been proposing exactly that, and there's a way if you don't want a separate class hierarchy.

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca

May 04, 2014
On 2014-05-03 14:28, monnoroch wrote:

> That leaves only to determine, what objects are scoped. Well, that is
> obviously stack-allocated structs, gc-allocated scope classes and
> gc-allocated structs in scope classes.

Will the destructor of GC allocated scope classes be called when its surrounding scope exists?

-- 
/Jacob Carlborg
May 04, 2014
On Saturday, 3 May 2014 at 12:28:03 UTC, monnoroch wrote:
> Back to the dtors: i understand, that all the stuff you propose could make GC faster, simpler, and cooler,

Note that this is _not_ the motivation behind the discussed changes. It's primarily about correctness and consistency. What we currently have if something that doesn't work at all in some cases (dynamic arrays, new with structs), and where it does work (class destructors) users have to conform to various rules as to what is allowed in a GC-called destructor (e.g. don't access references to other objects, don't throw (?), don't use thread-local globals, any probably many more subtle rules), that mostly cannot be enforced statically or even at runtime, potentially causing silent corruption if you fail to comply with them. This is IMO more than enough motivation to do something about it.

> but it sounds insane to anyone, who uses the language, not develops it, that if you create struct object, dror will be called, but if you place the copy in a container, it wont. It's just unanderstandable from user's point of view.

Not in a container, but making it GC managed. And IMO, it's unreasonable to expect deterministic behaviour from a tracing (non-precise) GC, which is inherently non-deterministic. The real problem is that you can currently do these things accidentally, without noticing it.

> 1) C.
> That is the simplest way: fully-manual resource management.
> It's obvious, we can't do that in D, because it's supposed to be simpler for coding, than C.

Again, the main motivation for GC is safety and enabling more idioms that would otherwise be impossible, _not_ lazyness on the part of the programmer.

> 3) C++.
> This one is semi-automatic (talking about user code, not some allocator libraries): you choose the scheme (refcounting, unique reference) and then it'll do the rest.
>
> 4) Rust.
> I'm not a pro here, but as i understand, it uses C++ way, and adds gc-collected pointers, but not sure, so help me here.

You could describe it like that, yes. But it's a lot more involved. In a way, Rust's owned types are the opposite of a GC: A GC destroys objects lazily and keeps them alive as long as they are referenced. Owned objects are destroyed eagerly at the end of their scope, but the type system ensures that there are no references to them at this point.

> What i propose, is to include new concept in D: scoped objects.
> Any object (no matter is it a class or struct instance) can be either scoped or not.
> Dtors for scoped objects are called when out of scope, dtors for non-scoped objects are not called at all.
>
> It is actually as simple as rewrite code
>
> A a = A();
>
> as
>
> A a = A();
> scope(exit)
>     a.~A();
>

There is std.typecons.scoped for that, and the deprecated scope classes. Also see deadalnix's `isolated` proposal:

http://forum.dlang.org/thread/yiwcgyfzfbkzcavuqdwz@forum.dlang.org

But I'm afraid your suggestion is unsafe: There also needs to be a way to guarantee that no references to the scoped object exist when it is destroyed.

I also don't think it's a good idea to have a hard-coded list of types that are scoped. This either needs to be specified by the user of the type (at instantion) and then become part of the type (like const), or it needs to be specified by the implementer of the type, as a requirement that it can only be instantiated as a scoped type, or as garbage-collected or reference-counted or ...
May 04, 2014
On Sunday, 4 May 2014 at 11:42:14 UTC, Marc Schütz wrote:
> On Saturday, 3 May 2014 at 12:28:03 UTC, monnoroch wrote:
>> Back to the dtors: i understand, that all the stuff you propose could make GC faster, simpler, and cooler,
>
> Note that this is _not_ the motivation behind the discussed changes. It's primarily about correctness and consistency. What we currently have if something that doesn't work at all in some cases (dynamic arrays, new with structs), and where it does work (class destructors) users have to conform to various rules as to what is allowed in a GC-called destructor (e.g. don't access references to other objects, don't throw (?), don't use thread-local globals, any probably many more subtle rules), that mostly cannot be enforced statically or even at runtime, potentially causing silent corruption if you fail to comply with them. This is IMO more than enough motivation to do something about it.

Case in point:
http://forum.dlang.org/thread/vlnjgtdmyolgoiofnfnl@forum.dlang.org
May 04, 2014
On 5/4/14, 4:42 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
> But I'm afraid your suggestion is unsafe: There also needs to be a way
> to guarantee that no references to the scoped object exist when it is
> destroyed.

Actually, it should be fine to call the destructor, then blast T.init over the object, while keeping the actual memory in the GC. This possible approach has come up a number of times, and I think it has promise. -- Andrei