digitalmars.D.learn - nogc associative array?
- aldanor (15/15) Dec 27 2014 Is there a way to do something like this while keeping the
- ketmar via Digitalmars-d-learn (20/36) Dec 27 2014 On Sat, 27 Dec 2014 23:43:54 +0000
- ketmar via Digitalmars-d-learn (30/46) Dec 27 2014 On Sat, 27 Dec 2014 23:43:54 +0000
Is there a way to do something like this while keeping the
destructor nogc?
class Foo {
shared static Foo[id] registry;
int id;
this(int id) {
this.id = id(
registry[id] = this;
}
~this() }. // ideally should be tagged as nogc
// nasty, memory corruption due to gc
registry.remove(id)f;
// however compiler doesn't warn about it...
}
}
Dec 27 2014
On Sat, 27 Dec 2014 23:43:54 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:
Is there a way to do something like this while keeping the=20
destructor nogc?
=20
class Foo {
shared static Foo[id] registry;
int id;
this(int id) {
this.id =3D id(
registry[id] =3D this;
}
~this() }. // ideally should be tagged as nogc
// nasty, memory corruption due to gc
registry.remove(id)f;
// however compiler doesn't warn about it...
}
}
oh, those dtor bites... in D dtor is "object finalizer", not more. it
essentially finalizes object fields that GC cannot finalize itself.
please, don't use object dtors for anything else, including modifying
global variables (and `registry` is a disguised global here).
besides, your dtor should never be called anyway, as the object is
always anchored in `registry`. what you need here is so called "weak
reference": reference to object which will not anchor it and will
become `null` when GD collects an object.
D has no official weak references for now, but you can emulate weak
refs, like in this code:
http://repo.or.cz/w/iv.d.git/blob_plain/HEAD:/weakref.d
but please note that this code is abusing both GC/druntime internals
and the fact that GC is working as it is working now. ;-)
as for your question: there is NO WAY to make GC working in dtors now.
removing AA item can cause rehashing, which in turn will cause GC
calls, which in turn will abort your program. it may seems to work and
then BANG! it's dead.
Dec 27 2014
On Sat, 27 Dec 2014 23:43:54 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:
Is there a way to do something like this while keeping the=20
destructor nogc?
=20
class Foo {
shared static Foo[id] registry;
int id;
this(int id) {
this.id =3D id(
registry[id] =3D this;
}
~this() }. // ideally should be tagged as nogc
// nasty, memory corruption due to gc
registry.remove(id)f;
// however compiler doesn't warn about it...
}
}
p.s. what you CAN do, on the other hand, is something like this:
shared static size_t[id] registry;
this (int id) {
...
regustry[id] =3D cast(size_t)cast(void*)this;
}
~this () {
auto me =3D (cast(size_t)cast(void*)this) in registry;
if (me !is null) *me =3D 0;
}
of course, you have to check if your object is the registry with the
code like this:
bool inRegistry (const(Foo) obj) {
auto me =3D (cast(size_t)cast(void*)obj) in registry;
return (me !is null && *me !=3D 0);
}
and you may consider eventual manual GC on registry by removing all 0
values from it. the easiest way to do this is to create a new AA and
copy all non-zero items to it.
please note that:
1. this code assumes that GC is not compacting (it's true for now, but
can be changed in future).
2. trick with `cast(size_t)cast(void*)` is unsafe: class can override
cast operation. you can use slightly safer and uglier code instead:
auto ptr =3D cast(size_t)*(cast(void**)&obj);
let the readers of your code to think a little what multiplication
operation for `cast(size_t)` mean. ;-)
Dec 27 2014









ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> 