Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Thursday, 19 August 2021 at 15:38:19 UTC, evilrat wrote:

On Thursday, 19 August 2021 at 15:12:03 UTC, Ferhat Kurtulmuş


Btw, based on 
https://github.com/dlang/druntime/blob/master/src/object.d#L4209:


import core.lifetime;
import core.stdc.stdio;
import core.stdc.stdlib;

extern (C) void rt_finalize(void *data, bool det=true) @nogc 
nothrow; // cheap hack here

alias destroy = rt_finalize;

class SomeClass
{
int a = 42;

this() @nogc { }
~this() @nogc {printf("nogc\n");}
this(int val) @nogc { a = val; }
}



@nogc void main()
{
	SomeClass dynAlloc = cast(SomeClass) 
malloc(__traits(classInstanceSize, SomeClass));

dynAlloc = emplace!SomeClass(dynAlloc, 123);
printf("dynamic %d\n", dynAlloc.a); // 123
//rt_finalize(cast(void*)dynAlloc);
destroy(cast(void*)dynAlloc); // cast needed :/ dunno 
consequences though

}


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Thursday, 19 August 2021 at 15:38:19 UTC, evilrat wrote:

On Thursday, 19 August 2021 at 15:12:03 UTC, Ferhat Kurtulmuş


This is cool, but even in unit tests for malloc wrapper there 
is only simple case with class without references to another 
class and no dtor.


If you examine the entire library, there are various use cases of 
nogc classes. For instance, a derived class containing references 
to other class objects [1]. I am not using classes heavily with 
D. I just once happily used dplug's nogc facilities. When I saw 
this thread, I just wanted to share it here.


Seems like the issue is that one have to add @nogc 
constructor/destructor overloads for emplace/destroy, and the 
author can't have @nogc dtor because of writeln (IIRC @nogc 
using GC is allowed with `debug` anyway), and all class members 
of another classes must recursively provide them as well.


I agree with you. D needs more nogc facilities for OOP. It would 
not be so hard to include those overloads. Probably, this would 
violate the strictly defended safety principles of D?


[1]: 
https://github.com/AuburnSounds/Dplug/blob/f67c14fd5ba44225d6669e87f942d641c8bf8ab8/window/dplug/window/cocoawindow.d


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Tejas via Digitalmars-d-learn

On Thursday, 19 August 2021 at 09:39:26 UTC, evilrat wrote:

On Thursday, 19 August 2021 at 08:25:23 UTC, Bienlein wrote:


Oops, I just realized that you can also not call emplace when 
@nogc is present. Well that is at least consistent with not 
either being able to call destroy ;-).


So, I guess this means that you can forget about manually 
allocating and freeing some instance of a class and using 
@nogc as well. That's a pitty, @nogc was a good idea.


you are probably doing something wrong, could you try @nogc 
ctor?


anyway @nogc is way too limiting, I don't see why bother when 
there is already `scope` storage (should work in nogc) and -vgc 
flag to show possible allocations.


```d

import core.lifetime;
import core.stdc.stdio;
import core.stdc.stdlib;

class SomeClass
{
int a = 42;

this() @nogc { }
this(int val) @nogc { a = val; }
}



@nogc void main()
{
byte[64] mem;
mem.emplace!SomeClass();
printf("stack %d\n", (cast(SomeClass) mem.ptr).a); // 42

scope a = new SomeClass();
printf("scope %d\n", a.a); //42

	SomeClass dynAlloc = cast(SomeClass) 
malloc(__traits(classInstanceSize, SomeClass));

dynAlloc = emplace!SomeClass(dynAlloc, 123);
printf("dynamic %d\n", dynAlloc.a); // 123
}
```


Allocating to a function local variable via ```new``` always 
allocates on stack assuming no arguments are passed to new


Read sentence 6 of 
https://dlang.org/spec/expression.html#new_expressions


So
```d
scope a = new SomeClass();
```
actually allocates on stack


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread evilrat via Digitalmars-d-learn
On Thursday, 19 August 2021 at 15:12:03 UTC, Ferhat Kurtulmuş 
wrote:

On Thursday, 19 August 2021 at 07:30:38 UTC, Bienlein wrote:

Hello,

I allocate some instance of class C manually and then free the 
memory again:


[...]


I just wanted to leave this here.
https://github.com/AuburnSounds/Dplug/blob/master/core/dplug/core/nogc.d


This is cool, but even in unit tests for malloc wrapper there is 
only simple case with class without references to another class 
and no dtor.


Seems like the issue is that one have to add @nogc 
constructor/destructor overloads for emplace/destroy, and the 
author can't have @nogc dtor because of writeln (IIRC @nogc using 
GC is allowed with `debug` anyway), and all class members of 
another classes must recursively provide them as well.


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Thursday, 19 August 2021 at 07:30:38 UTC, Bienlein wrote:

Hello,

I allocate some instance of class C manually and then free the 
memory again:


[...]


I just wanted to leave this here.
https://github.com/AuburnSounds/Dplug/blob/master/core/dplug/core/nogc.d


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Bienlein via Digitalmars-d-learn
This works, vit. Thanks! I thought it wouldn't, because your code 
still makes use of embrace. But it somehow worked, although I 
don't understand why ... ;-).


I also added a constructor using the same approach as your 
destructor and this also worked:


 this(int otherNum) @nogc {
 this.num = otherNum;
 debug writeln("this: ", this.num);
 }

@evilrat: Will try what you suggested after work today. Too busy 
now.





Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread evilrat via Digitalmars-d-learn

On Thursday, 19 August 2021 at 08:25:23 UTC, Bienlein wrote:


Oops, I just realized that you can also not call emplace when 
@nogc is present. Well that is at least consistent with not 
either being able to call destroy ;-).


So, I guess this means that you can forget about manually 
allocating and freeing some instance of a class and using @nogc 
as well. That's a pitty, @nogc was a good idea.


you are probably doing something wrong, could you try @nogc ctor?

anyway @nogc is way too limiting, I don't see why bother when 
there is already `scope` storage (should work in nogc) and -vgc 
flag to show possible allocations.


```d

import core.lifetime;
import core.stdc.stdio;
import core.stdc.stdlib;

class SomeClass
{
int a = 42;

this() @nogc { }
this(int val) @nogc { a = val; }
}



@nogc void main()
{
byte[64] mem;
mem.emplace!SomeClass();
printf("stack %d\n", (cast(SomeClass) mem.ptr).a); // 42

scope a = new SomeClass();
printf("scope %d\n", a.a); //42

	SomeClass dynAlloc = cast(SomeClass) 
malloc(__traits(classInstanceSize, SomeClass));

dynAlloc = emplace!SomeClass(dynAlloc, 123);
printf("dynamic %d\n", dynAlloc.a); // 123
}
```


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread vit via Digitalmars-d-learn

On Thursday, 19 August 2021 at 08:25:23 UTC, Bienlein wrote:

On Thursday, 19 August 2021 at 07:30:38 UTC, Bienlein wrote:

Hello,

I allocate some instance of class C manually and then free the 
memory again:


class C {
int num;

~this() {
writeln("~this");
}
}

void foo() // @nogc
{
auto mem = cast(C)malloc(__traits(classInstanceSize, 
C));

auto c = emplace!(C)(mem);

c.num = 789;

destroy(c);
free(cast(void*) c);
c = null;
}

int main()
{
foo();
}

The code above works well as the destructor of c in class C is 
called by destroy. Problem is that destroy cannot be used once 
function foo is annotated with @nogc. There seems to be no way 
round it.


What I want is to keep the function foo annotated with @nogc, 
but still have the destructor of C be called before free is 
called. Is there a way to call the destructor through meta 
programming or some kind of reflection so that I can create 
some generic function that calls the destructor and then free 
for any kind of class?


Thanks, Bienlein


Oops, I just realized that you can also not call emplace when 
@nogc is present. Well that is at least consistent with not 
either being able to call destroy ;-).


So, I guess this means that you can forget about manually 
allocating and freeing some instance of a class and using @nogc 
as well. That's a pitty, @nogc was a good idea.


Try this:
```d
import std;
import core.stdc.stdlib : malloc, free;

class C {
int num;

~this() @nogc{
debug writeln("~this");
}
}

void foo()  @nogc
{
auto mem = cast(C)malloc(__traits(classInstanceSize, C));
auto c = emplace!(C)(mem);

c.num = 789;

destruct(c);
free(cast(void*) c);
c = null;
}

void main()
{
foo();
}



//https://github.com/atilaneves/automem/blob/master/source/automem/utils.d

void destruct(T)(T obj) if (is(T == class)) {
(cast(_finalizeType!T) _finalize)(() @trusted { return 
cast(void*) obj; }());

}


private extern(C){
	void rt_finalize(void* p, bool det = true) @trusted @nogc pure 
nothrow;


template _finalizeType(T) {
import std.traits: Unqual;
static if (is(Unqual!T == Object)) {
alias _finalizeType = typeof(_finalize);
} else {
import std.traits : BaseClassesTuple;
import std.meta : AliasSeq;
alias _finalizeType = typeof(function void(void* p, 
bool det = true) {
// generate a body that calls all the destructors 
in the chain,
// compiler should infer the intersection of 
attributes

foreach (B; AliasSeq!(T, BaseClassesTuple!T)) {
// __dtor, i.e. B.~this
static if (__traits(hasMember, B, "__dtor"))
() { B obj; obj.__dtor; } ();
// __xdtor, i.e. dtors for all RAII members
static if (__traits(hasMember, B, "__xdtor"))
() { B obj; obj.__xdtor; } ();
}
});
}
}
}
```


Re: How to call destructor before free without dropping @nogc?

2021-08-19 Thread Bienlein via Digitalmars-d-learn

On Thursday, 19 August 2021 at 07:30:38 UTC, Bienlein wrote:

Hello,

I allocate some instance of class C manually and then free the 
memory again:


class C {
int num;

~this() {
writeln("~this");
}
}

void foo() // @nogc
{
auto mem = cast(C)malloc(__traits(classInstanceSize, 
C));

auto c = emplace!(C)(mem);

c.num = 789;

destroy(c);
free(cast(void*) c);
c = null;
}

int main()
{
foo();
}

The code above works well as the destructor of c in class C is 
called by destroy. Problem is that destroy cannot be used once 
function foo is annotated with @nogc. There seems to be no way 
round it.


What I want is to keep the function foo annotated with @nogc, 
but still have the destructor of C be called before free is 
called. Is there a way to call the destructor through meta 
programming or some kind of reflection so that I can create 
some generic function that calls the destructor and then free 
for any kind of class?


Thanks, Bienlein


Oops, I just realized that you can also not call emplace when 
@nogc is present. Well that is at least consistent with not 
either being able to call destroy ;-).


So, I guess this means that you can forget about manually 
allocating and freeing some instance of a class and using @nogc 
as well. That's a pitty, @nogc was a good idea.


How to call destructor before free without dropping @nogc?

2021-08-19 Thread Bienlein via Digitalmars-d-learn

Hello,

I allocate some instance of class C manually and then free the 
memory again:


class C {
int num;

~this() {
writeln("~this");
}
}

void foo() // @nogc
{
auto mem = cast(C)malloc(__traits(classInstanceSize, C));
auto c = emplace!(C)(mem);

c.num = 789;

destroy(c);
free(cast(void*) c);
c = null;
}

int main()
{
foo();
}

The code above works well as the destructor of c in class C is 
called by destroy. Problem is that destroy cannot be used once 
function foo is annotated with @nogc. There seems to be no way 
round it.


What I want is to keep the function foo annotated with @nogc, but 
still have the destructor of C be called before free is called. 
Is there a way to call the destructor through meta programming or 
some kind of reflection so that I can create some generic 
function that calls the destructor and then free for any kind of 
class?


Thanks, Bienlein