www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - nogc associative array?

reply "aldanor" <i.s.smirnov gmail.com> writes:
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
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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
prev sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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