digitalmars.D.learn - How to initialize a globle variable nicely and properly?
- Heromyth (81/81) Dec 14 2018 We have a module including many globle variables which are needed
- Rubn (22/104) Dec 14 2018 The problem here is that you are creating a new thread in the
- Neia Neutuladh (7/13) Dec 14 2018 When you start a D thread, thread-local static constructors get run. So
- Heromyth (6/21) Dec 15 2018 Yes, it's very dangerous to create a new thread in shared static
- Neia Neutuladh (5/8) Dec 15 2018 The runtime, more likely. There are plenty of problems in this vein that...
We have a module including many globle variables which are needed to be initialized firstly in "shared static this() {}", see here https://github.com/huntlabs/hunt/blob/master/source/hunt/time/Init.d. The problem is that these variables are not always initialized firstly when are referenced by some others moudles in "static this() {}". Here is a demo to illustrate it. ////////////////// // module A ////////////////// module test.A; import std.stdio; import core.thread; import core.time; class A { __gshared int sharedField; shared static this() { writeln("running A in shared static this(), sharedField=", sharedField); Thread th = new Thread(() { }); th.start(); Thread.sleep(100.msecs); sharedField = 2; writeln("running A done in shared static this(), sharedField=", sharedField); } static this() { writeln("running A in static this(), sharedField=", sharedField); } } ////////////////// // module B ////////////////// module test.B; import test.A; import std.stdio; import core.thread; shared static this() { writeln("running in shared static this() from B"); } class B { shared static this() { writeln("running B in shared static this(), sharedField=", A.sharedField); } static this() { // bug is here writeln("running B in static this(), sharedField=", A.sharedField); } } ////////////////// // module main ////////////////// import std.stdio; import test.A; import core.thread; void main() { writeln("running in main."); } ////////////////// // output ////////////////// Running ./demo running A in shared static this(), sharedField=0 running A in static this(), sharedField=0 running B in static this(), sharedField=0 // bug is here running A done in shared static this(), sharedField=2 running in shared static this() from B running B in shared static this(), sharedField=2 running A in static this(), sharedField=2 running B in static this(), sharedField=2 running main. ==================== You can see the sharedField is 0 in B's static this() at first. If Thread is disabled to run in shared static this(), this problem seems to be fixed. Some related bugs: 1) https://issues.dlang.org/show_bug.cgi?id=6114 2) https://issues.dlang.org/show_bug.cgi?id=4923
Dec 14 2018
On Saturday, 15 December 2018 at 02:54:55 UTC, Heromyth wrote:We have a module including many globle variables which are needed to be initialized firstly in "shared static this() {}", see here https://github.com/huntlabs/hunt/blob/master/source/hunt/time/Init.d. The problem is that these variables are not always initialized firstly when are referenced by some others moudles in "static this() {}". Here is a demo to illustrate it. ////////////////// // module A ////////////////// module test.A; import std.stdio; import core.thread; import core.time; class A { __gshared int sharedField; shared static this() { writeln("running A in shared static this(), sharedField=", sharedField); Thread th = new Thread(() { }); th.start(); Thread.sleep(100.msecs); sharedField = 2; writeln("running A done in shared static this(), sharedField=", sharedField); } static this() { writeln("running A in static this(), sharedField=", sharedField); } } ////////////////// // module B ////////////////// module test.B; import test.A; import std.stdio; import core.thread; shared static this() { writeln("running in shared static this() from B"); } class B { shared static this() { writeln("running B in shared static this(), sharedField=", A.sharedField); } static this() { // bug is here writeln("running B in static this(), sharedField=", A.sharedField); } } ////////////////// // module main ////////////////// import std.stdio; import test.A; import core.thread; void main() { writeln("running in main."); } ////////////////// // output ////////////////// Running ./demo running A in shared static this(), sharedField=0 running A in static this(), sharedField=0 running B in static this(), sharedField=0 // bug is here running A done in shared static this(), sharedField=2 running in shared static this() from B running B in shared static this(), sharedField=2 running A in static this(), sharedField=2 running B in static this(), sharedField=2 running main. ==================== You can see the sharedField is 0 in B's static this() at first. If Thread is disabled to run in shared static this(), this problem seems to be fixed. Some related bugs: 1) https://issues.dlang.org/show_bug.cgi?id=6114 2) https://issues.dlang.org/show_bug.cgi?id=4923The problem here is that you are creating a new thread in the `shared static this()`. shared static this() { writeln("running A in shared static this(), sharedField=", sharedField); Thread th = new Thread(() { }); // Calls `static this()` including B's `static this()` th.start(); Thread.sleep(100.msecs); sharedField = 2; writeln("running A done in shared static this(), sharedField=", sharedField); } static this() { writeln("running A in static this(), sharedField=", sharedField); } Creating a new thread causes those thread's constructor `static this()` to be called. You need to create your threads somewhere else or have the values be initialized before the threads are created.
Dec 14 2018
On Sat, 15 Dec 2018 02:54:55 +0000, Heromyth wrote:shared static this() { writeln("running A in shared static this(), sharedField=", sharedField); Thread th = new Thread(() { }); th.start();When you start a D thread, thread-local static constructors get run. So don't start threads until your shared static constructors finish. If I encountered something like this, I would set up a queue of actions to be run at the start of main() and fill them with static constructors. Instead of this static constructor creating a thread, it would enqueue a delegate that starts the thread.
Dec 14 2018
On Saturday, 15 December 2018 at 03:48:15 UTC, Neia Neutuladh wrote:On Sat, 15 Dec 2018 02:54:55 +0000, Heromyth wrote:Yes, it's very dangerous to create a new thread in shared static this(). For a big project, it sometimes hard to identify this problem. Maybe, the compiler should do something for this, should it?shared static this() { writeln("running A in shared static this(), sharedField=", sharedField); Thread th = new Thread(() { }); th.start();When you start a D thread, thread-local static constructors get run. So don't start threads until your shared static constructors finish. If I encountered something like this, I would set up a queue of actions to be run at the start of main() and fill them with static constructors. Instead of this static constructor creating a thread, it would enqueue a delegate that starts the thread.
Dec 15 2018
On Sat, 15 Dec 2018 13:49:03 +0000, Heromyth wrote:Yes, it's very dangerous to create a new thread in shared static this(). For a big project, it sometimes hard to identify this problem. Maybe, the compiler should do something for this, should it?The runtime, more likely. There are plenty of problems in this vein that the compiler can't detect, but the runtime should be able to detect all of them. Filed https://issues.dlang.org/show_bug.cgi?id=19492
Dec 15 2018