Strategies for resolving cyclic dependencies in static ctors

Michel Fortin michel.fortin at michelf.com
Tue Mar 22 07:14:11 PDT 2011


On 2011-03-22 05:16:31 -0400, Max Samukha <max at spam.box> said:

> ----
> module foo_helper;
> 
> private extern(C) foo_static_ctor();
> static this()
> {
>      foo_static_ctor();
> }
> 
> -----
> 
> module foo;
> import foo_helper;
> 
> private Object global;
> private extern(C) void foo_static_ctor()
> {
>      global = new Object;
> }
> ----
> 
> Note that "global" is guaranteed to have been initialized when accessed 
> from static constructors in modules that import "a".

I don't know why people keep repeating that falacy. This statement is 
true only as long as there are no circular dependencies. It should 
read: "'global' is guarentied to have been initialized when access from 
static constructors in module that import 'a' _and_ which are not 
imported by 'a', directly or indirectly."

Because once you introduce a circular dependency, you get this:

----
module foo_helper;

private extern(C) foo_static_ctor();
static this() { foo_static_ctor(); }
-----
module foo;
import foo_helper;
import bar;

private Object global;
private extern(C) void foo_static_ctor()
{
     global = new Object;
     bar.testGlobal();
}
public void testGlobal()
{
     assert(global);
}
----
module bar_helper;

private extern(C) bar_static_ctor();
static this() { bar_static_ctor(); }
-----
module bar;
import bar_helper;
import foo;

private Object global;
private extern(C) void bar_static_ctor()
{
     global = new Object;
     foo.testGlobal();
}
public void testGlobal()
{
     assert(global);
}
----

Note how foo_static_ctor() and bar_static_ctor() each calls a function 
that needs the global variable of the other module to be initialized. 
It should be obvious that it can't work. If you doubt me, try it.


> Being able to instruct the compiler to do this implicitly (so we could 
> put static ctors in templates, for example) would probably solve most 
> of static ctor problems.

It'd have the exact same effect as adding a pragma to bypass the check 
for circular dependencies, while making things more complicated.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list