Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
How it works
There's a fair amount of processing going on under the hood of RCC++, but here's a brief overview of the technique:
- At compile time a set of macros and templates generate file name information and dependency information for the code from the markup added by the developer.
- At startup time the executable (or any dll's using RCC++) creates a global instance of the PerModuleInterface to which a constructor for every runtime modifiable class is added, and through which a SystemTable instance is available to provide access to application globals.
- Runtime Modifiable classes are instantiated through a factory, unless they are auto-constructed singletons (in which case they are auto constructed during the initialization phase).
- Virtual interfaces are used to allow functions to be accessed via a pointer to an object, and for swapping the pointer to swap the code called.
- All files which can be runtime compiled are monitored by a file change monitor.
- When a file changes, it is compiled along with any dependencies and dependent files into a module (dll/so). Note that this step relies on the developer markup provided and performs as minimal as possible a compile and link (in the smallest case only two object files may be compiled and linked into a module).
- The module is loaded if a compile is successful, and the state of all runtime modifiable class instances is serialized out, new objects are constructed for the code which has changed, the state is serialized back in and the old objects are deleted.
- Error recovery protects much of this in case of errors in the code and object swap / serialization process.
- Any runtime modifiable classes should have serialized out their pointers through an object id system so that on reload they point to the new instances.
- Non runtime modifiable code should ensure that an OnConstructorsAdded listener is added, and on being called they should change object pointers using the object id.
This is relatively complicated, but it significantly increases the performance of making changes over compiling a whole module along with loading and saving the entire state.