strange work of GC

2015-02-06 Thread Andrey Derzhavin via Digitalmars-d-learn


class C1
{
int a1, b1, c1, d1, e1;
string sdb1;
this(string s)
{
sdb1 = s;
a1=90;
b1=19;
d1=22;
e1=23;
}

~this()
{
if (sdb1 == "lll")
{
sdb1 = "aaa";
}

writeln("disposing "~sdb1);
}
}

class C2
{
C1 c1 = null;
int a2, b2, c2, d2, e2;
string sdb2;
this(string s)
{
sdb2 = s;
a2=90;
b2=19;
d2=22;
e2=23;
}

~this()
{

c1=null;
writeln("disposing "~sdb2);
}
};

void fn1()
{
writeln("start of fn1");
C2[] arr = new C2[1_000_000];

for (int i=0; iThis code never starts the garbage collector, but after execution 
fn1 nothing refers to arr.
As I think, the garbage collector should start destoying of the 
C1 and C2 objects of arr array during the "while" cycle prosess, 
but this does not

happen. Dtors are not called.
If I use the manual destroying of objects C1 and C2 by "destroy" 
method, the dtors of C1 and C2 objects are normally called, but 
it can't be safe.
If I use the GC.collect method after fn1, I get an error: 
"core.exception.InvalidMemoryOperationError@(0)".

Is this a bug of GC or I do something wrong?

Thanks.




Re: strange work of GC

2015-02-06 Thread anonymous via Digitalmars-d-learn
On Friday, 6 February 2015 at 20:38:07 UTC, Andrey Derzhavin 
wrote:
As I think, the garbage collector should start destoying of the 
C1 and C2 objects of arr array during the "while" cycle 
prosess, but this does not

happen. Dtors are not called.


Garbage is only collected when you allocate memory. You're just 
`sleep`ing in the loop which doesn't allocate anything, and so it 
doesn't trigger garbage collections.


If I use the manual destroying of objects C1 and C2 by 
"destroy" method, the dtors of C1 and C2 objects are normally 
called, but it can't be safe.


right

If I use the GC.collect method after fn1, I get an error: 
"core.exception.InvalidMemoryOperationError@(0)".

Is this a bug of GC or I do something wrong?


This is you GC allocating in a destructor (the writeln calls). 
The GC can't handle that.


Re: strange work of GC

2015-02-06 Thread Adam D. Ruppe via Digitalmars-d-learn
On Friday, 6 February 2015 at 20:38:07 UTC, Andrey Derzhavin 
wrote:
As I think, the garbage collector should start destoying of the 
C1 and C2 objects of arr array during the "while" cycle 
prosess, but this does not

happen. Dtors are not called.


The D GC only runs on demand - typically, when you allocate new 
memory is when the gc might run. This keeps totally hidden pauses 
from happening, so you at least can avoid a collection at a bad 
time for your program.


If I use the GC.collect method after fn1, I get an error: 
"core.exception.InvalidMemoryOperationError@(0)".

Is this a bug of GC or I do something wrong?


You used GC memory from inside a destructor. That's an illegal 
operation; read the tip of the week from Sunday's newsletter to 
see a bit more:


http://arsdnet.net/this-week-in-d/feb-01.html


Re: strange work of GC

2015-02-06 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 6 February 2015 at 21:07:14 UTC, anonymous wrote:
This is you GC allocating in a destructor (the writeln calls). 
The GC can't handle that.


Note that it isn't writeln itself, it is the ~ used in building 
the string. If you change that to a comma, it'll work better 
(writeln can take multiple arguments and avoid allocating an 
intermediate string (sometimes))


Re: strange work of GC

2015-02-07 Thread Andrey Derzhavin via Digitalmars-d-learn


If a "destroy" method is used together with GC inside of my 
app,it makes my app unstable.
In this case I need to choose how to destroy my objects: 1) 
always manually by method "destroy", but without GC; 2) or always 
automatically by GC, but without using the "destroy" method.
In the first case I need to know how can I disable the automatic 
GC in my app?
In the second case - how can I disable the "destroy" method calls 
inside of my app?


Re: strange work of GC

2015-02-07 Thread FG via Digitalmars-d-learn

On 2015-02-07 at 12:02, Andrey Derzhavin wrote:

If a "destroy" method is used together with GC inside of my app,it makes my app 
unstable.
In this case I need to choose how to destroy my objects: 1) always manually by method 
"destroy", but without GC; 2) or always automatically by GC, but without using the 
"destroy" method.
In the first case I need to know how can I disable the automatic GC in my app?
In the second case - how can I disable the "destroy" method calls inside of my 
app?


Why do you want to use destroy? Put GC.collect() after the call to fn1 and GC 
cleanup will work just fine[1], I've checked. Are you talking about a different 
program now?

[1] Assuming that you compile the program as 64-bit and not 32-bit.


Re: strange work of GC

2015-02-07 Thread Andrey Derzhavin via Digitalmars-d-learn

Why do you want to use destroy?
The destroy method always calls a dtor of the objects, where I 
can destroy some
object's variables in that order that I need, I think. And this 
is very good for me, because I have a full control of the 
object's destroying stage.
But if I use the GC, I have no garanties that the dtors will be 
called, therefore some of my methods will not be called too. In 
this case
it would be better to disable automatically garbage collection in 
my D app, elsewise once app will be failed (manual destroying 
idiom).


On another hand if I use only GC (automatically destroying 
idiom), I have to disable "destroy" method and all dtors of the 
objects,
so that nobody can call "destroy" method. Otherwise app will be 
failed once again.


Two idioms are existing in one app at the same time have more 
possiblities for D programmers to make hard errors in their code,

and it is confusing me sometimes.

For example, .Net (C#) have no dtors and "destroy" methods. It is 
a very good idiom, because no confusions occur.


Re: strange work of GC

2015-02-07 Thread Mike Parker via Digitalmars-d-learn

On 2/8/2015 4:32 AM, Andrey Derzhavin wrote:

Why do you want to use destroy?

The destroy method always calls a dtor of the objects, where I can
destroy some
object's variables in that order that I need, I think. And this is very
good for me, because I have a full control of the object's destroying
stage.
But if I use the GC, I have no garanties that the dtors will be called,
therefore some of my methods will not be called too. In this case
it would be better to disable automatically garbage collection in my D
app, elsewise once app will be failed (manual destroying idiom).

On another hand if I use only GC (automatically destroying idiom), I
have to disable "destroy" method and all dtors of the objects,
so that nobody can call "destroy" method. Otherwise app will be failed
once again.

Two idioms are existing in one app at the same time have more
possiblities for D programmers to make hard errors in their code,
and it is confusing me sometimes.

For example, .Net (C#) have no dtors and "destroy" methods. It is a very
good idiom, because no confusions occur.


You shouldn't think of destructors as they are in C++. They're more akin 
to finalizers in Java and C#. You should never use them to clean up any 
GC memory or implement any operations which touch GC memory.


In your case, forget destructors and the destroy method. Just implement 
a common method on all of your objects that need cleanup (perhaps name 
it 'terminate') and call that. This gives you the deterministic 
destruction that you want (the same as calling destroy on each object) 
while avoiding the possibility that the GC can call your cleanup method.


Re: strange work of GC

2015-02-07 Thread FG via Digitalmars-d-learn

On 2015-02-08 at 01:20, Mike Parker wrote:

In your case, forget destructors and the destroy method. Just implement a 
common method on all of your objects that need cleanup (perhaps name it 
'terminate') and call that. This gives you the deterministic destruction that 
you want (the same as calling destroy on each object) while avoiding the 
possibility that the GC can call your cleanup method.


What is wrong with doing all that in a destructor? I don't know if it is just 
an implementation detail, but a destroyed object is either zero-filled or 
reinitialized to the default, so, if implemented correctly, it knows whether a 
cleanup is required (and I'm assuming that a model of simple single ownership 
is used, like in Qt). Therefore it should be safe to use destroy to finalize an 
object and even to put destroy in its destructor in order to perform a 
controlled cascade destruction of all the children that require immediate 
cleanup (ie. releasing expensive non-GC resources, closing connections, etc.). 
The main difference with C++ being that you would only force finalization, but 
then let the GC free the memory in its normal fashion.





Re: strange work of GC

2015-02-07 Thread Mike Parker via Digitalmars-d-learn

On 2/8/2015 11:32 AM, FG wrote:

On 2015-02-08 at 01:20, Mike Parker wrote:

In your case, forget destructors and the destroy method. Just
implement a common method on all of your objects that need cleanup
(perhaps name it 'terminate') and call that. This gives you the
deterministic destruction that you want (the same as calling destroy
on each object) while avoiding the possibility that the GC can call
your cleanup method.


What is wrong with doing all that in a destructor? I don't know if it is
just an implementation detail, but a destroyed object is either
zero-filled or reinitialized to the default, so, if implemented
correctly, it knows whether a cleanup is required (and I'm assuming that
a model of simple single ownership is used, like in Qt). Therefore it
should be safe to use destroy to finalize an object and even to put
destroy in its destructor in order to perform a controlled cascade
destruction of all the children that require immediate cleanup (ie.
releasing expensive non-GC resources, closing connections, etc.). The
main difference with C++ being that you would only force finalization,
but then let the GC free the memory in its normal fashion.



First, there are no guarantees about when or if a destructor is going to 
be called. The fact that the current GC calls the destructors of all 
live objects at application shutdown is an implementation detail. If you 
want deterministic destruction, you can not rely on destructors.


Second, if you are going to call destroy on every object to clean them 
up, then in principle that's fine. But now you have to be careful that 
no mistakes slip into the code base, e.g. forgetting to call destroy on 
an object that touches GC memory in its destructor.


By separating resource cleanup from object destruction, you get both 
deterministic cleanup and more freedom in choosing whether or not to 
clean up at all. I used to be obsessive about cleaning up everything at 
app exit (my C background, I suppose). These days, I've come around to 
the view that it's fine just to let the OS handle it. I put a terminate 
method in every class that allocates any sort of resource. If I need to 
free those resources at runtime, I call terminate and let the GC worry 
about the object when it needs to. At app exit, I only call terminate on 
objects that absolutely need to do something before the process exits, 
like writing a final message to a log file, or sending a See You Later 
packet to a server. Everything else I just let go and leave to the OS to 
deal with. There's no reason to do otherwise. In essence, resource 
cleanup only happens when and if I say. That just isn't possible if all 
cleanup is in destructors. You either have to destroy *every* object 
yourself, or be vigilant about which objects you let the GC call 
destructors on.


Re: strange work of GC

2015-02-08 Thread FG via Digitalmars-d-learn

On 2015-02-08 at 06:36, Mike Parker wrote:

On 2/8/2015 11:32 AM, FG wrote:

On 2015-02-08 at 01:20, Mike Parker wrote:

In your case, forget destructors and the destroy method. Just
implement a common method on all of your objects that need cleanup
(perhaps name it 'terminate') and call that. This gives you the
deterministic destruction that you want (the same as calling destroy
on each object) while avoiding the possibility that the GC can call
your cleanup method.


What is wrong with doing all that in a destructor? I don't know if it is
just an implementation detail, but a destroyed object is either
zero-filled or reinitialized to the default, so, if implemented
correctly, it knows whether a cleanup is required (and I'm assuming that
a model of simple single ownership is used, like in Qt). Therefore it
should be safe to use destroy to finalize an object and even to put
destroy in its destructor in order to perform a controlled cascade
destruction of all the children that require immediate cleanup (ie.
releasing expensive non-GC resources, closing connections, etc.). The
main difference with C++ being that you would only force finalization,
but then let the GC free the memory in its normal fashion.




First, there are no guarantees about when or if a destructor is going to be 
called. The fact that the current GC calls the destructors of all live objects 
at application shutdown is an implementation detail. If you want deterministic 
destruction, you can not rely on destructors.


I admit that I became accustomed to that implementation detail and would like 
it to stay.


Second, if you are going to call destroy on every object to clean them up, then 
in principle that's fine. But now you have to be careful that no mistakes slip 
into the code base, e.g. forgetting to call destroy on an object that touches 
GC memory in its destructor.


One could also forget to call terminate(). :)

The advantage of ~this() is that it is standard, while terminate() is not. You 
call it that, someone else might call it finalize(), close() or whatever. I do 
see a benefit in using terminate() directly instead of the GC-fired destructor, 
because it's not constrained by having to steer clear of the 
InvalidMemoryOperationError, but it is overshadowed by inconvenience. So let's 
assume that terminate() is GC-friendly (ie. would work even when called from a 
destructor).


By separating resource cleanup from object destruction, you get both 
deterministic cleanup and more freedom in choosing whether or not to clean up 
at all.


I separate them only when the object needs it (flush a write, close a 
connection, release a big chunk of memory, etc.), by calling destroy and not 
waiting until the GC decides that it's time to deallocate memory for that 
object and performs the destruction by itself. For every other case of object I 
also do not care when and if it gets cleaned up.


At app exit, I only call terminate on objects that absolutely need to do 
something before the process exits, like writing a final message to a log file 
[...] resource cleanup only happens when and if I say.


Exactly, but if I put a call to terminate() in the destructor, then clean up 
will be automated in those cases when I don't care about cleaning up myself or 
*forget* to do it.


That just isn't possible if all cleanup is in destructors. You either have to 
destroy *every* object yourself, or be vigilant about which objects you let the 
GC call destructors on.


Why not? Are you saying that because of the lack of guarantees that a 
destructor will be called by the GC? And not *every* object -- it was stated 
that we don't care about all those objects that don't require special clean up.