static this(), interdepencies, and bootstrapping

Jason House jason.james.house at gmail.com
Sun Aug 3 05:33:23 PDT 2008


Derek Ney wrote:

> I am working on an interpreted language written in D. It has an object
> structure similar to ruby. There is a set of about 10 classes that form
> the base of the object hierarchy. Bootstraping the hierarchy at startup is
> tricky and I have based it all on static this() calls. The static this()
> calls register the different classes so a run-time table can be created
> which knows about all the different classes and their bootstrapping calls.
> 
> Unfortunately when I finally got it compiled for the first time, and ran
> it, I got this error from the D runtime (from std/moduleinit.d in fact):
> 
> Error: circular initialization dependency with module base
> 
> Looking at the code for moduleinit.d (I am using D2.0, 2.017 compiler) I
> see that it is this guarantee of the order in which static this() is
> called that is causing my problem. In my case I do not care at all about
> the order in which the static this() calls are called. I designed it to
> not care about that order. But there does not appear to be any way to tell
> D that I do not care and so none of this code will work. I noted that
> moduleinit.d does have a "ictor" member in ModuleInfo that is labeled
> "order independent ctor". I would love to use that, but I do not see
> anyway to do that. Is there some way of specifying that a static this()
> call is order independent?
> 
> To illustrate my problem, here is a short set of 3 files that uses a
> "bootstrap" template to create a table called boot_call_table that maps a
> name to the boot function for the class. The table gets filled in by
> static this() in the mixin "Bootstrap". In main() it iterates over the
> table and calls each boot function. Here is the code:
> 
> -----File mod_a.d-----
> module mod_a;
> 
> import bootstrap;
> import mod_b;
> 
> import std.stdio;
> 
> class A
> {
>   B ref_to_b;
> 
>   static void boot_class_a(string name)
>   {
>     writeln("bootstrap name: ", name);
>     // initialize some A stuff...
>   }
> 
>   mixin Bootstrap!(boot_class_a, "class A");
> }
> 
> void main()
> {
>   // boot all the things up
>   foreach(string name, BootCall call; boot_call_table)
>   {
>     call(name);
>   }
> }
> ----- File mod_b.d -----
> module mod_b;
> 
> import bootstrap;
> import mod_a;
> 
> import std.stdio;
> 
> class B
> {
>   A ref_to_a;
> 
>   static void boot_class_b(string name)
>   {
>     writeln("bootstrap name: ", name);
>     // initialize some B stuff...
>   }
> 
>   mixin Bootstrap!(boot_class_b, "class B");
> }
> ----- File bootstrap.d -----
> module bootstrap;
> 
> alias void function(string) BootCall;
> 
> BootCall[string] boot_call_table;
> 
> // mixin that will cause boot_call to be made at startup
> template Bootstrap(alias boot_call, string name)
> {
>   static this()
>   {
>     boot_call_table[name] = &boot_call;
>   }
> }
> ----- end of files -----
> 
> This sample will generate the error "Error: circular initialization
> dependency with module mod_a". If you comment out the mixin Bootstrap!
> call in mod_b.d and recompile, it will run fine and print "bootstrap name:
> class A" as expected.
> 
> I know that this "ordering" of static this() calls was added to 2.0
> presumably because people did not like the non-deterministic order in
> which they were called. But for my application, there is no way I can get
> rid of the "circular" nature (except for putting every single class into
> one gigantic file). Is there some trick that someone has for me to get an
> order independent static this() like call?
> -Thanks, Derek

The problem with the sample has nothing to do with the boot call table
(except that it's why you have static initialization).  The following
sample should cause the error as well:

module A;
import B;
class A{
  B ref_to_b;
  static this(){}
}
==========
module B;
import A;
class B{
  A ref_to_a;
  static this(){}
}



More information about the Digitalmars-d mailing list