Ce qui suit me donne une violation d'accès sur Windows 32-bit, dmd.2.052, pas de drapeaux. Lorsque le destructeur est exécuté par le ramasseur d'ordures, la boîte de message semble être corrompue dans le processus.
import std.stdio;
import core.thread;
import core.memory;
import std.concurrency;
class C
{
string m_str;
Tid m_receiverTid;
this(string s, Tid rt) { this.m_str = s; this.m_receiverTid = rt; }
~this() { writeln("Destructor : ",this.m_str);
m_receiverTid.send(this.m_str);
}
}
void receiver() {
try {
while(true) {
receive((string s){writeln("Received: ",s);});
}
} catch (Throwable th) {
writeln("Caught throwable: ",th.toString());
}
}
void main() {
Tid receiverTid = spawn(&receiver);
receiverTid.send("Basic test");
Thread.sleep( 5_000_000 );
C c1 = new C("c1 Manually deleted",receiverTid);
delete c1;
Thread.sleep( 5_000_000 );
{
C c2 = new C("c2 Garbage collected",receiverTid);
}
writeln("Running garbage collector..."); // This line needed to flush out the c2 root pointer.
GC.collect();
Thread.sleep( 5_000_000 );
writeln("Exiting main thread...");
}
Ce qui précède produit :
Reçu : Test de base
Destructeur : c1 Suppression manuelle
Reçu : c1 Supprimé manuellement
Exécution du garbage collector...
Destructeur : c2 Garbage collected
Reçu : c2 Garbage collected
Attrapé throwable : object.Error : Violation d'accès
Sortie du fil principal...
Existe-t-il des solutions de contournement pour cela ?
Existe-t-il un moyen pour le code du destructeur de savoir s'il est invoqué par le GC ou non ?
Le passage de messages à partir d'un destructeur est-il intrinsèquement dangereux, par exemple si des threads non GC sont gelés par le GC alors qu'ils ont un verrou mutex sur une boîte de messages partagée, alors le GC pourrait se bloquer s'il envoie à une boîte de messages verrouillée ? Ou bien le code du destructeur n'intervient-il que dans un cycle de balayage après que tous les threads ont été dégelés ?
Est-il possible qu'un destructeur fasse référence au stockage local d'un thread, par exemple, le cycle de balayage du GC pourrait-il se dérouler dans un autre thread ?