Danol

Dlang : shared static this recursive denial workaround

Mar 6th, 2015
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 2.44 KB | None | 0 0
  1. module straw.core_test.a;
  2.  
  3. import std.stdio;
  4. import straw.core.hooks;
  5.  
  6. @callOnAppInit()
  7. void moduleInit() {
  8.     writeln( "Called" );
  9. }
  10.  
  11. // --------------------------------------------------------------------------------
  12. module straw.core.hooks;
  13.  
  14. import std.array;
  15. import std.conv;
  16. import std.typetuple;
  17.  
  18. /**
  19.  * !!! USE callOnAppInit() NOT ONLY callOnAppInit, OTHERWISE IT WON'T WORK !!!
  20.  * .
  21.  * Use this as an attribute to mark a function that will be automatically called on app init (shared static this time).
  22.  * The desired function has to be in the root of the module and has to be public. The function must be of type 'void function()';
  23.  * This is a workaround for using shared static this, which isn't allowed in any two modules that are imported in each another.
  24.  * The call order between modules in unspecified, it is expected that you only register hooks in marked routine.
  25.  * */
  26. auto callOnAppInit( string module_ = __MODULE__, string function_ = __FUNCTION__, size_t line_ = __LINE__ )() {
  27.     static assert( !function_.length, "@callOnAppInit has to be used in root!" );
  28.     return Attr_CallOnAppInit!( module_, line_ )();
  29. }
  30.  
  31. private struct Attr_CallOnAppInit( string module_, size_t line_ ) {
  32.  
  33. private:
  34.     enum IS_ATTR_CallOnAppInit = true;
  35.     enum ATTR_LINE = line_;
  36.  
  37. private:
  38.     shared static this() {
  39.         mixin( "static import " ~ module_ ~ ";" );
  40.         alias moduleAlias = TypeTuple!( mixin( module_ ) );
  41.  
  42.         mixin( {
  43.                 size_t numFound;
  44.                 string result;
  45.  
  46.                 foreach( memName; __traits( derivedMembers, moduleAlias ) ) {
  47.                     static if( __traits( compiles, __traits( getMember, moduleAlias, memName ) ) ) {
  48.                         foreach( attribute; __traits( getAttributes, __traits( getMember, moduleAlias, memName ) ) ) {
  49.                             static if( __traits( compiles, attribute.IS_ATTR_CallOnAppInit ) && attribute.ATTR_LINE == line_ ) {
  50.                                 static assert( is( typeof( &__traits( getMember, moduleAlias, memName ) ) == void function() ), "The function '" ~ memName ~ "' in module '"  ~ module_ ~ "' is of type '" ~ ( typeof( __traits( getMember, moduleAlias, memName ) ) ).stringof ~ "' not of type 'void function()'!" );
  51.  
  52.                                 result ~= "__traits( getMember, moduleAlias, \"" ~ memName ~ "\" )();\n";
  53.                                 numFound ++;
  54.                             }
  55.                         }
  56.                     }
  57.                 }
  58.  
  59.                 assert( numFound, "Could not find any relevant @callOnAppInit rutines in module '" ~ module_ ~ "' (#" ~ line_.to!string ~ "). Perhaps you marked it private?" );
  60.                 return result;
  61.             } () );
  62.     }
  63.  
  64. }
Advertisement
Add Comment
Please, Sign In to add comment