Re: Can't I allocate at descontructor?

2021-03-07 Thread Guillaume Piolat via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:28:58 UTC, Ali Çehreli wrote:
To my surprise, even though 'c' is not null below, the 
destructor is not executed multiple times.




Hence why 
https://p0nce.github.io/d-idioms/#GC-proof-resource-class works 
as a detector of undeterminism.





Re: Can't I allocate at descontructor?

2021-03-05 Thread Ali Çehreli via Digitalmars-d-learn

On 3/5/21 8:29 PM, Jack wrote:

> Now about the behavior of a static destructor, like static ~this() { }
> is this guaranteed to be run?

I don't know any way of creating a module on the GC heap so their 
destruction should not be related to GC collection. I would expect all 
'static ~this()' blocks to be executed upon thread termination.


'shared static ~this()' blocks are said to be executed after main() 
exits in the following page but that description is not precise enough 
because 'shared static ~this()' blocks of a dynamic library would be 
executed when the library is unloaded.


  https://dlang.org/spec/class.html#SharedStaticConstructor

Ali



Re: Can't I allocate at descontructor?

2021-03-05 Thread Mike Parker via Digitalmars-d-learn

On Saturday, 6 March 2021 at 04:29:41 UTC, Jack wrote:

Now about the behavior of a static destructor, like static 
~this() { } is this guaranteed to be run?


Yes. Some perspective:

1. During program execution, class/struct destructors on 
stack-allocated instances are  invoked when the instances go out 
of scope.


2. During program execution, class/struct destructors on 
GC-allocated instances are only called when the GC determines the 
instances are no longer referenced AND it needs to reclaim 
memory. There is no way to know when or if this will happen 
during the program's execution. Short-lived programs may never 
need to reclaim memory, so the destructors may never be called. 
The longer a program runs, and the more it allocates from the GC 
heap, the more likely it is that a given object's destructor will 
be called during execution since the GC will need to reclaim 
memory more often. This is a consequence of relying on the GC to 
manage memory.


3. After the main function exits, the runtime will invoke all 
module destructors. They do not belong to any class or struct 
instance, nor are they managed by the GC. They will always 
execute.


4. After module destructors are invoked, the GC will begin its 
shutdown. By default, it will invoke the destructors on every 
class/struct instance for which it hasn't. This can be disabled 
via a command-line argument for DRuntime.


So with the current implementation, all GC-managed class and 
struct destructors will end up being called at some point. But 
the spec does not require the GC to invoke destructors during 
shutdown--that's an implementation detail. Moreover, since the 
person executing the program can turn that behavior off via a 
command-line argument, you can't rely on the default behavior 
anyway. So that's why the documentation says that class and 
struct destructors are not guaranteed to be invoked by the GC.


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 21:24:08 UTC, tsbockman wrote:

On Friday, 5 March 2021 at 21:17:24 UTC, tsbockman wrote:

On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:

class C {...}

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
 ...

...
import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
...


Also, that's not the correct way to manually allocate a class 
on the heap. C.sizeof is the size of a reference to C, not an 
instance of C, and we need to blit and construct the instance 
before it is safe to use:


import core.memory : GC;
C c = cast(C) GC.malloc(__traits(classInstanceSize, C));
import core.lifetime : emplace;
emplace(c, anyConstructorArgsGoHere);
...


good catch, thanks


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 21:25:52 UTC, Ali Çehreli wrote:

On 3/5/21 12:57 PM, Jack wrote:

>> destroy() executes the destructor.
>
> but I would need to call it manually and only after I
somewhat I've
> determined I no longer need the resources, right? so
destroy(c) would be
> no different from calling my own finalize-like method like
freeResources()?

Yes but perhaps with some extra functionality like the optional 
'initialize':


  https://dlang.org/phobos/object.html#.destroy

Ali


Now about the behavior of a static destructor, like static 
~this() { } is this guaranteed to be run?


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:
On Fri, Mar 05, 2021 at 08:24:26PM +, Jack via 
Digitalmars-d-learn wrote:

On Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:
> On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:

[...]

> > But the ones heap may never run at all, is that right?
> 
> You can't rely on the garbage collector for deterministic 
> destruction, no.


Are there some kind of replacement or I have to make my own 
finalize-like method, once I determine somewhat the 
application no longer need those resources?

[...]

If you know when you can deallocate something, that means you 
don't need the GC to collect it,


I'll modify the program so that I know the right state to call my 
finalize-like method or just destroy(c). Until I find out that 
destrutor behavior, I was going to just use the destrutor


 so you could just allocate it
on the malloc heap instead, and call destroy/free once you're 
done.  You could use the C version of malloc/free.  You can 
also optionally use GC.malloc/GC.free.


E.g.:

class C {...}

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
... // use c

// We're done with c, destroy it
destroy(c); // this will call the dtor
GC.free(cast(void*) c);
	c = null; // optional, just to ensure we don't accidentally 
use it again



T


I'll do something like this, thanks



Re: Can't I allocate at descontructor?

2021-03-05 Thread Ali Çehreli via Digitalmars-d-learn

On 3/5/21 12:57 PM, Jack wrote:

>> destroy() executes the destructor.
>
> but I would need to call it manually and only after I somewhat I've
> determined I no longer need the resources, right? so destroy(c) would be
> no different from calling my own finalize-like method like 
freeResources()?


Yes but perhaps with some extra functionality like the optional 
'initialize':


  https://dlang.org/phobos/object.html#.destroy

Ali



Re: Can't I allocate at descontructor?

2021-03-05 Thread tsbockman via Digitalmars-d-learn

On Friday, 5 March 2021 at 21:17:24 UTC, tsbockman wrote:

On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:

class C {...}

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
 ...

...
import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
...


Also, that's not the correct way to manually allocate a class on 
the heap. C.sizeof is the size of a reference to C, not an 
instance of C, and we need to blit and construct the instance 
before it is safe to use:


import core.memory : GC;
C c = cast(C) GC.malloc(__traits(classInstanceSize, C));
import core.lifetime : emplace;
emplace(c, anyConstructorArgsGoHere);
...



Re: Can't I allocate at descontructor?

2021-03-05 Thread tsbockman via Digitalmars-d-learn

On Friday, 5 March 2021 at 21:02:08 UTC, H. S. Teoh wrote:
If you know when you can deallocate something, that means you 
don't need the GC to collect it, so you could just allocate it 
on the malloc heap instead, and call destroy/free once you're 
done.  You could use the C version of malloc/free.  You can 
also optionally use GC.malloc/GC.free.


E.g.:

class C {...}

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
... // use c

// We're done with c, destroy it
destroy(c); // this will call the dtor
GC.free(cast(void*) c);
	c = null; // optional, just to ensure we don't accidentally 
use it again


Unless the function is nothrow, that should really be:

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
scope(exit) {
// We're done with c, destroy it
destroy(c); // this will call the dtor
GC.free(cast(void*) c);
c = null; // optional, just to ensure we don't 
accidentally use it again

}
... // use c

Or,

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
try {
... // use c
} finally {
// We're done with c, destroy it
destroy(c); // this will call the dtor
GC.free(cast(void*) c);
c = null; // optional, just to ensure we don't 
accidentally use it again

}



Re: Can't I allocate at descontructor?

2021-03-05 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Mar 05, 2021 at 08:24:26PM +, Jack via Digitalmars-d-learn wrote:
> On Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:
> > On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:
[...]
> > > But the ones heap may never run at all, is that right?
> > 
> > You can't rely on the garbage collector for deterministic
> > destruction, no.
> 
> Are there some kind of replacement or I have to make my own
> finalize-like method, once I determine somewhat the application no
> longer need those resources?
[...]

If you know when you can deallocate something, that means you don't need
the GC to collect it, so you could just allocate it on the malloc heap
instead, and call destroy/free once you're done.  You could use the C
version of malloc/free.  You can also optionally use GC.malloc/GC.free.

E.g.:

class C {...}

import core.memory : GC;
C c = cast(C) GC.malloc(C.sizeof);
... // use c

// We're done with c, destroy it
destroy(c); // this will call the dtor
GC.free(cast(void*) c);
c = null; // optional, just to ensure we don't accidentally use it again


T

-- 
Freedom of speech: the whole world has no right *not* to hear my spouting off!


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:28:58 UTC, Ali Çehreli wrote:

On 3/5/21 12:24 PM, Jack wrote:

Are there some kind of replacement or I have to make my own 
finalize-like method, once I determine somewhat the 
application no longer need those resources?


destroy() executes the destructor.


but I would need to call it manually and only after I somewhat 
I've determined I no longer need the resources, right? so 
destroy(c) would be no different from calling my own 
finalize-like method like freeResources()?


To my surprise, even though 'c' is not null below, the 
destructor is not executed multiple times.


import std.stdio;

class C {
  string fileName;

  this(string fileName) {
writeln("constructing");
this.fileName = fileName;
writeln("creating file");
  }

  ~this() {
writeln("destructing");
if (fileName) {
  writeln("removing the file");

} else {
  writeln("NOT removing the file");
}
  }
}

void main() {
  auto c = new C("some imaginary file name");

  // Executes the destructor
  destroy(c);

  // This does not do anything
  destroy(c);

  // Neither does this
  import core.memory;
  GC.collect();
}

Ali





Re: Can't I allocate at descontructor?

2021-03-05 Thread Ali Çehreli via Digitalmars-d-learn

On 3/5/21 12:24 PM, Jack wrote:

Are there some kind of replacement or I have to make my own 
finalize-like method, once I determine somewhat the application no 
longer need those resources?


destroy() executes the destructor.

To my surprise, even though 'c' is not null below, the destructor is not 
executed multiple times.


import std.stdio;

class C {
  string fileName;

  this(string fileName) {
writeln("constructing");
this.fileName = fileName;
writeln("creating file");
  }

  ~this() {
writeln("destructing");
if (fileName) {
  writeln("removing the file");

} else {
  writeln("NOT removing the file");
}
  }
}

void main() {
  auto c = new C("some imaginary file name");

  // Executes the destructor
  destroy(c);

  // This does not do anything
  destroy(c);

  // Neither does this
  import core.memory;
  GC.collect();
}

Ali


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:18:44 UTC, Max Haughton wrote:

On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:

On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:

On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:

On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:

[...]


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


thanks for such good article. So if the object was allocated 
on heap, there's no guarantee that the object's destrutor 
will be called at all? do destrutor allocate at stack are 
guarantee to be run?


Destructors of structs on the stack will always run 
deterministically.


But the ones heap may never run at all, is that right?


You can't rely on the garbage collector for deterministic 
destruction, no.


Are there some kind of replacement or I have to make my own 
finalize-like method, once I determine somewhat the application 
no longer need those resources? aside from destructor for memory 
allocated on stack, what are uses for destrutors?


Re: Can't I allocate at descontructor?

2021-03-05 Thread Max Haughton via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:13:54 UTC, Jack wrote:

On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:

On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:

On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:

[...]


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


thanks for such good article. So if the object was allocated 
on heap, there's no guarantee that the object's destrutor 
will be called at all? do destrutor allocate at stack are 
guarantee to be run?


Destructors of structs on the stack will always run 
deterministically.


But the ones heap may never run at all, is that right?


You can't rely on the garbage collector for deterministic 
destruction, no.


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:10:39 UTC, Max Haughton wrote:

On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:

On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it 
did happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


thanks for such good article. So if the object was allocated 
on heap, there's no guarantee that the object's destrutor will 
be called at all? do destrutor allocate at stack are guarantee 
to be run?


Destructors of structs on the stack will always run 
deterministically.


But the ones heap may never run at all, is that right?


Re: Can't I allocate at descontructor?

2021-03-05 Thread Max Haughton via Digitalmars-d-learn

On Friday, 5 March 2021 at 20:03:58 UTC, Jack wrote:

On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it 
did happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


thanks for such good article. So if the object was allocated on 
heap, there's no guarantee that the object's destrutor will be 
called at all? do destrutor allocate at stack are guarantee to 
be run?


Destructors of structs on the stack will always run 
deterministically.


Re: Can't I allocate at descontructor?

2021-03-05 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Mar 05, 2021 at 08:03:58PM +, Jack via Digitalmars-d-learn wrote:
> On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:
> > On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
> > > The following code returns a memory error. I did notice it did
> > > happens whenever I did a memory allocation. Is this not possible
> > > in the descontrutor? if so, why?
> > 
> > https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/
> 
> thanks for such good article. So if the object was allocated on heap,
> there's no guarantee that the object's destrutor will be called at all?

Yes.

And also if it does get called, there's no guarantee what order it will
be called in w.r.t. other dtors. And you cannot perform any GC
operations in it.


> do destrutor allocate at stack are guarantee to be run?

Yes.


T

-- 
If it tastes good, it's probably bad for you.


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 09:23:29 UTC, Mike Parker wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it did 
happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


thanks for such good article. So if the object was allocated on 
heap, there's no guarantee that the object's destrutor will be 
called at all? do destrutor allocate at stack are guarantee to be 
run?


Re: Can't I allocate at descontructor?

2021-03-05 Thread Jack via Digitalmars-d-learn

On Friday, 5 March 2021 at 05:42:03 UTC, evilrat wrote:

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it did 
happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?




GC prohibits allocation during collection, since this dtor is 
likely called by GC this is what happens.


If you REALLY need this just allocate using other mechanisms.


I didn't know that, it seems even if I use other allocation 
mechanism there's no guarantee the deconstructor will be called 
so it seems the native descontrutor will not be of help at all


Re: Can't I allocate at descontructor?

2021-03-05 Thread Mike Parker via Digitalmars-d-learn

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it did 
happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?


https://dlang.org/blog/2021/03/04/symphony-of-destruction-structs-classes-and-the-gc-part-one/


Re: Can't I allocate at descontructor?

2021-03-04 Thread evilrat via Digitalmars-d-learn

On Friday, 5 March 2021 at 05:31:38 UTC, Jack wrote:
The following code returns a memory error. I did notice it did 
happens whenever I did a memory allocation. Is this not 
possible in the descontrutor? if so, why?




GC prohibits allocation during collection, since this dtor is 
likely called by GC this is what happens.


If you REALLY need this just allocate using other mechanisms.


Can't I allocate at descontructor?

2021-03-04 Thread Jack via Digitalmars-d-learn
The following code returns a memory error. I did notice it did 
happens whenever I did a memory allocation. Is this not possible 
in the descontrutor? if so, why?



core.exception.InvalidMemoryOperationError@src\core\exception.d(647): Invalid 
memory operation


import std.stdio;

int main()
{
auto a = new A;
return 0;
}

class A
{
this() { }

~this()
{
f();
}
}

void f()
{
auto str = new string[100];
}