Function Aliasing ----------------- Author: Tom Goodale, Gabrielle Allen Date: February 2000-February 2001 Why --- For a while we've wanted function aliasing so that different thorns providing the same implementation can also provide functions with the same name, and thus thorns using these can be independent of the actual active thorn. Specification ------------- Function definitions will go in interface.ccl. (At the moment all functions will be public, maybe for 4.1 we will think about making private functions) Define Function (In both Providing and Using Thorn): FUNCTION [PROVIDED-BY [LANGUAGE ]] Providing Thorn: PROVIDE FUNCTION WITH [LANGUAGE ] Using Thorn: USES FUNCTION Details and Questions --------------------- 1. Private, Protected, Public: May not be any point doing this, probably no need until 4.1. We can make the overloaded name something horrible, and use #defines to convert the alias-name to these horrible things, 'though that may cause problems in Fortran, but perhaps there we can use the f_file_preprocessor to change things independent of case. 2. Notation FUNCTION (Going with this for now) or FUNCTION: ... RETURNS 3. Allow different independent implementations to provide functions with the same name but which are only visable to their children. This would be nice, but it gets nasty with Fortran 4. schedule.ccl ? In the schedule.ccl we can have PROVIDE FUNCTION WITH which allows run-time choosing via if statements in the schedule.ccl 5. How to define arrays in the arguement list? CCTK_INT *foo CCTK_INT (array) foo CCTK_INT:ARRAY foo ARRAY(CCTK_INT) foo 6. What can't we cope with? For fortran wrappers - strings not at the end - more than 3 strings Implementation -------------- The CST parses the interface.ccl files and creates files to make overloadable functions for each different thorn function. The Cactus overloading macros are used for this. ThornOverloadables.h (in bindings/include) - include file for the overload macros, containing information about arguments and return types for each function alias. OverloadThorns.c (in src/main) - routines to overload the thorn functions, and the function CCTKi_BindingsSetupThornFunctions which will set up all aliased functions to initially be dummy functions. This routine is called from CCTKi_InitialiseSubsystemDefaults in Subsystems.c DummyThornFunctions.c (in bindings/Functions) - the dummy functions for each alias FortranThornFunctions.c (in bindings/Functions) - the fortran wrapper for each alias _Register.c (in bindings/Functions) - register aliased routines for a thorn RegisterThornFunctions.c (in bindings/Functions) - containing function CCTKi_BindingsRegisterThornFunctions which calls all the individual thorn registration functions for active thorns. This function is called from CCTKi_InitialiseCactus cctk_FunctionAliases.h (in src/include) (which will be included in cctk.h) - prototypes for aliased functions need to change this so that only the functions used in a thorn are here to prevent recompiling everything Still To Add ------------ Calls to CCTK_IsFunctionOverloaded("function name") for protecting calls to overloaded functions in thorns Alternative Implementation -------------------------- This would allow steering CCTK_CreateAliasFunction(const char *name, void (*variable)(void) void (*default)(void), const char *signature, const char *argnames, int steerable) Only the first three being essential, so the rest can be missed off for now. This puts an entry on a hash table of structs like typedef struct { void (*variable)(void); void (*default)(void); char *signature; char *argnames; int steerable; } iAliasFunction; and sets it to the default, or if the function already exists in the hash table, checks that then signature and argnames are equivalent. (This gives us runtime checking as well as the compile time checking from the perl, so this will extend to when we have dynamically loadable libraries for thorns.) Then we have CCTK_ProvideFunction(const char *name, void (*function)(void)) which basically sets the value of "variable" in the above to the "function" in this call. Calls to the above, plus the header file containing the proper prototype for the function, and the line declaring the variable for the function, need to be generated by perl. We also have CCTK_IsFunctionAliased(const char *name) which checks to see if it is the default, or some better value. Ok, so the above gives us everything in the current plan. To increase flexibility, we can extend the syntax in the .ccl file to allow one to associate a BOOLEAN parameter with the PROVIDE FUNCTION statement, so people can choose in a parameter file whether or not that thorn should provide the function. To make things steerable, the above needs to be extended ... typedef IALIASTHORN { IALIASTHORN *next; char *thorn; void (*function)(void); } iAliasThorn; typedef struct { void (*variable)(void); void (*default)(void); char *signature; char *argnames; int steerable; iAliasThorn *thornlist; int n_steered; } iAliasFunction; Then the Provide function just adds to the thornlist. We also then have CCTK_AliasFunction(const char *function, const char *thorn) which looks through the thornlist and sets the value of "variable" to the appropriate function. Now the use of the BOOLEAN parameter above doesn't work too well for the steerable case. We could in principle, and it's something I wan to add in 4.1, associate an action with the changing of a parameter. This would be a generally nice feature for steerable parameters, as it means you no longer need to manually check if the value has changed, you can just trigger something when it does change. However, we are on feature freeze here, so this will wait until 4.1. Anyway, for this situation it's still not nice, as we would need to add an Unalias function for when the boolean goes false, and people would need to change two parameters to steer it. The alternative is to automatically generate a flesh private KEYWORD parameter. Something like cctk::AliasFrom = "" which would have to have a default of "flesh" to use the dummy and be automatically steered if there was only one active thorn providing the function. This is really ugly. Anyway, I think steering the things can wait until 4.1 too, as it wasn't in the original spec, and it'll be work. So, in conclusion, my current thoughts are that we either stick with using the overload macros for the moment, since that's almost all there now, and leave everything else till 4.1, or that we go for the second set of structures above, since that gives us more queryable information as to what can alias and what has aliased, and it allows the BOOLEAN approach for deciding whether to alias or not. In either case I think steering can wait until 4.1.