digitalmars.D - Order of Static Construction
- Dru (7/7) Jan 04 2019 from the spec:
- Rubn (10/18) Jan 04 2019 The shared static constructor would only be able to access one of
- Dru (28/28) Jan 04 2019 @Rubn
- Neia Neutuladh (25/34) Jan 04 2019 This part of the spec isn't entirely correct. Consider:
- Steven Schveighoffer (26/66) Jan 04 2019 Unfortunately, that's not how it can work. Shared constructors run once
- Dru (8/8) Jan 05 2019 Construction order is resolved by module dependencies (import
- Steven Schveighoffer (6/15) Jan 07 2019 This is a really good idea, actually. I hadn't thought of that approach
- Steven Schveighoffer (5/21) Jan 07 2019 Note that this still doesn't solve the current problem of a thread
- Steven Schveighoffer (3/4) Jan 07 2019 https://issues.dlang.org/show_bug.cgi?id=19556
from the spec: "Shared static constructors on all modules are run before any non-shared static constructors." Is there a specific reason, or is it just for simplicity? There could be a situation where a shared ctor depends on a thread local variable. Preferably, the variable is only initialized in a non-shared ctor.
Jan 04 2019
On Friday, 4 January 2019 at 13:27:29 UTC, Dru wrote:from the spec: "Shared static constructors on all modules are run before any non-shared static constructors." Is there a specific reason, or is it just for simplicity? There could be a situation where a shared ctor depends on a thread local variable. Preferably, the variable is only initialized in a non-shared ctor.The shared static constructor would only be able to access one of the thread-local variables (probably from the main thread). That isn't very useful. It'd be more useful to have thread local static constructors access variables that were constructed in the shared static constructor. The thread constructor is called any time a new thread is created, and you can create a new thread any time at runtime. It'd be impossible to guarantee the shared static constructor is called after all the thread local constructors unless you put a bunch of restrictions on threads.
Jan 04 2019
Rubn yes from the main thread I'll give a specific example lets say every thread has its own log so log should be a thread local object and lets say we want to log from a shared static ctor log module ----------- (define Log class ...) Log log; static this() { log = new Log; } other module ----------- import log_module; (define other class ...) shared Other other; shared static this() { log.write("creating other"); //seg fault log is null! other = new Other; } Neia Neutuladh you're right the statement doesn't consider starting threads. if we strictly follow the spec then yes it should error, but I think maybe we should change the spec and mix between shared/non-shared if there isn't a good reason not to
Jan 04 2019
On Fri, 04 Jan 2019 13:27:29 +0000, Dru wrote:from the spec: "Shared static constructors on all modules are run before any non-shared static constructors." Is there a specific reason, or is it just for simplicity? There could be a situation where a shared ctor depends on a thread local variable. Preferably, the variable is only initialized in a non-shared ctor.This part of the spec isn't entirely correct. Consider: --- shared static this() { writeln("shared ctor start"); new Thread({}).start; Thread.sleep(10.seconds); writeln("shared ctor done"); } static this() { writeln("non-shared ctor"); } --- This prints: shared ctor start non-shared ctor shared ctor done In order to fix this, the compiler would have to defer running threads until static constructors finish. But a static constructor that starts a thread could easily be waiting for it to finish and yield a result before continuing, leading to deadlocks. In https://issues.dlang.org/show_bug.cgi?id=19492, I suggested a warning or error instead of trying to do the right thing.
Jan 04 2019
On 1/4/19 11:48 AM, Neia Neutuladh wrote:On Fri, 04 Jan 2019 13:27:29 +0000, Dru wrote:Unfortunately, that's not how it can work. Shared constructors run once per program. So trivially, any thread run after main() has started will be run after the shared ctors have run. Some thread-local constructors depend on this, so you can't do it the other way around. What you could do is initialize the logger in a function, then call that function from either the shared or thread local constructor, depending on whether it's already initialized or not (you can check without locking, since it's a thread-local).from the spec: "Shared static constructors on all modules are run before any non-shared static constructors." Is there a specific reason, or is it just for simplicity? There could be a situation where a shared ctor depends on a thread local variable. Preferably, the variable is only initialized in a non-shared ctor.This part of the spec isn't entirely correct. Consider: --- shared static this() { writeln("shared ctor start"); new Thread({}).start; Thread.sleep(10.seconds); writeln("shared ctor done"); } static this() { writeln("non-shared ctor"); } --- This prints: shared ctor start non-shared ctor shared ctor doneRight. This supersedes the normal order, and can potentially cause issues.In order to fix this, the compiler would have to defer running threads until static constructors finish. But a static constructor that starts a thread could easily be waiting for it to finish and yield a result before continuing, leading to deadlocks.Exactly right. There has been some abuse of what shared static constructors are for in a lot of libraries. Until recently, vibe.d encouraged putting the HTTP server setup into a static constructor, including initializing the socket listeners. This kind of thing is prone to errors, because you can't truly be certain of static construction of everything in the first thread. This would not be as bad of a problem if the shared constructors were only allowed to access data initialized by shared constructors. But there's no designation in D for that.In https://issues.dlang.org/show_bug.cgi?id=19492, I suggested a warning or error instead of trying to do the right thing.Might be the right thing. Another possibility to still allow starting threads from shared ctors is to wait for the shared ctors to finish, but only yield an error if they don't finish in a certain amount of time (like 4 seconds). That way, a thread can still be started if the shared ctors don't depend on the execution of the thread progressing. Should have some documentation to go along with this. -Steve
Jan 04 2019
Construction order is resolved by module dependencies (import statements) In the main thread ---------------------- Currently, shared and thread-local construction are separated. Instead we could "construct a module", i.e run both shared and thread-local construction for that module, then continue to construct the next module.
Jan 05 2019
On 1/5/19 10:22 AM, Dru wrote:Construction order is resolved by module dependencies (import statements) In the main thread ---------------------- Currently, shared and thread-local construction are separated. Instead we could "construct a module", i.e run both shared and thread-local construction for that module, then continue to construct the next module.This is a really good idea, actually. I hadn't thought of that approach at all. I think it can be done in druntime as well, without depending on compiler changes. I will post an enhancement request to track it. Thanks! -Steve
Jan 07 2019
On 1/7/19 5:02 PM, Steven Schveighoffer wrote:On 1/5/19 10:22 AM, Dru wrote:Note that this still doesn't solve the current problem of a thread running static ctors before the main thread's shared static ctors are done. We should deal with that as well. -SteveConstruction order is resolved by module dependencies (import statements) In the main thread ---------------------- Currently, shared and thread-local construction are separated. Instead we could "construct a module", i.e run both shared and thread-local construction for that module, then continue to construct the next module.This is a really good idea, actually. I hadn't thought of that approach at all. I think it can be done in druntime as well, without depending on compiler changes. I will post an enhancement request to track it. Thanks!
Jan 07 2019
On 1/7/19 5:02 PM, Steven Schveighoffer wrote:I will post an enhancement request to track it. Thanks!https://issues.dlang.org/show_bug.cgi?id=19556 -Steve
Jan 07 2019