www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - cyclic redundancy

reply Mr.Bingo <Bingo Namo.com> writes:
I have static this scattered throughout. Some are module static 
this and some are struct and class.


In a test case I have reduced to a struct that uses a static this 
and I get a cycle... even though, of course, the static this does 
nothing accept internal things.

It is very annoying to have to hack these cycles. while they can 
be bypassed for testing but production requires passing a runtime 
argument which is useless for distribution to users.

The cyclic testing is so ignorant that it effectively makes using 
any static this with any type of complex importing impossible, 
even though no cycles actually exist.


Something new has to be done.

I propose that some way be made to disable a static this from 
being included in the testing:

 NoCyclicRedundancyCheck static this()
{

}

I'm not sure if attributes will persist at runtime though. Any 
method is better than what we have now which essentially prevents 
all static this usage because one can't guarantee that the future 
won't create a cycle and then the program will break with no easy 
fix.
Jun 18 2018
next sibling parent reply Mr.Bingo <Bingo Namo.com> writes:
I got tired of waiting for a solution and rolled my own:



static this()
{

	import std.meta, std.stdio;

	// Find all <module>___This functions linked to this module
	auto Iterate()()
	{
		string[string] s;
		void Iterate2(alias m, int depth = 0)()
		{
			static if (depth < 4)
			{		
				static foreach (symbol_name; __traits(allMembers, m))
				{			

					static if (symbol_name == "object") { }
					else static if (symbol_name == m.stringof[7..$]~"___This")
					{
						s[m.stringof[7..$]] = m.stringof[7..$]~"___This";
					} else static if (isModule!(__traits(getMember, m, 
symbol_name)))
						{
							mixin("Iterate2!("~symbol_name~", depth + 1);");
						}
				}
			}
		}

		mixin("Iterate2!("~.stringof[7..$]~");");

		return s;
	}


	// Call all
	enum fs = Iterate;
	static foreach(k, f; fs)
		mixin(k~"."~f~"();");	
}


This code simply finds all <module>___This static functions 
linked to the module this static constructor is called from and 
executes them.

This doesn't solve the original problem but lets one execute the 
static functions to simulate static this. One could 
hypothetically even add attributes to allow for ordering(which is 
what the original cyclic redundancy check is suppose to solve but 
makes things worse since it is an ignorant algorithm).

This type of method might be more feasible, a sort of static 
main(). It does not check for static this of aggregates though 
but gets around the CRC's banket fatal error.
Jun 18 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/18/18 4:45 AM, Mr.Bingo wrote:
 I got tired of waiting for a solution and rolled my own:
 
 
 
 static this()
 {
 
      import std.meta, std.stdio;
 
      // Find all <module>___This functions linked to this module
      auto Iterate()()
      {
          string[string] s;
          void Iterate2(alias m, int depth = 0)()
          {
              static if (depth < 4)
              {
                  static foreach (symbol_name;
__traits(allMembers, m))
                  {
 
                      static if (symbol_name == "object") { }
                      else static if (symbol_name == 
 m.stringof[7..$]~"___This")
                      {
                          s[m.stringof[7..$]] =
m.stringof[7..$]~"___This";
                      } else static if
(isModule!(__traits(getMember, m, 
 symbol_name)))
                          {
                             
mixin("Iterate2!("~symbol_name~", depth + 
 1);");
                          }
                  }
              }
          }
 
          mixin("Iterate2!("~.stringof[7..$]~");");
 
          return s;
      }
 
 
      // Call all
      enum fs = Iterate;
      static foreach(k, f; fs)
          mixin(k~"."~f~"();");
 }
 
 
 This code simply finds all <module>___This static functions linked to 
 the module this static constructor is called from and executes them.
 
 This doesn't solve the original problem but lets one execute the static 
 functions to simulate static this. One could hypothetically even add 
 attributes to allow for ordering(which is what the original cyclic 
 redundancy check is suppose to solve but makes things worse since it is 
 an ignorant algorithm).
The algorithm in druntime is correct, I'm sure you mean that the data provided to the algorithm is not detailed enough. This is actually a very tricky thing to get right. What you may end up with is a program that works or doesn't based on your linker order.
 This type of method might be more feasible, a sort of static main(). It 
 does not check for static this of aggregates though but gets around the 
 CRC's banket fatal error.
The worst thing to consider is template class/struct static ctors which get called in the *instantiating* module. I always recommend avoiding putting those into your code. -Steve
Jun 18 2018
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/18/18 3:19 AM, Mr.Bingo wrote:
 I have static this scattered throughout. Some are module static this and 
 some are struct and class.
 
 
 In a test case I have reduced to a struct that uses a static this and I 
 get a cycle... even though, of course, the static this does nothing 
 accept internal things.
 
 It is very annoying to have to hack these cycles. while they can be 
 bypassed for testing but production requires passing a runtime argument 
 which is useless for distribution to users.
 
 The cyclic testing is so ignorant that it effectively makes using any 
 static this with any type of complex importing impossible, even though 
 no cycles actually exist.
Indeed, the module dependency information is very coarse, so it's very easy to have "fake" cycles. All we look at is which modules import other modules. Note that the cycle detection and ordering is correct, given the limited information the compiler provides.
 Something new has to be done.
 
 I propose that some way be made to disable a static this from being 
 included in the testing:
 
  NoCyclicRedundancyCheck static this()
 {
 
 }
I'd love to see something like this. Note that the cycle check is not for redundancy, but for ordering how to call the static ctors. What you really want to call this is IndependentCtor or something like that. This means that this segment of the static ctor does not depend on anything initialized by other static ctors, and so can be called at any time.
 I'm not sure if attributes will persist at runtime though. Any method is 
 better than what we have now which essentially prevents all static this 
 usage because one can't guarantee that the future won't create a cycle 
 and then the program will break with no easy fix.
It would effectively split the static ctors into 2 functions, one that can be called independently, and one that has to be sorted. How this is normally handled is the compiler makes "fake" modules so it can put that moduleinfo somewhere. -Steve
Jun 18 2018