In openEMS, all extensions are subclasses from the abstract Engine_Extension to implement features like Engine_Extension::Apply2Voltages(). When an Engine_Extension is created, it accepts a pointer to Engine. Simulation data is taken from the Engine using virtual functions like Engine::GetVolt().
Because virtual functions prevent the compiler from inlining the code, in order to select the non-virtual functions, each extension repeats the same simulation code repeated many times using non-virtual subclass engine functions in a big if/else check, e.g. 2 different Apply2Voltages(), one calls Engine::GetVolt(), another calls Engine_sse::GetVolt(). This led to code duplication and poor readability.
I found it's extremely difficult to do any development within these Extensions due to the code duplication problem. I've already tried 2 solutions:
Convert all Engine_Extension classes to a template Engine_Extension<typename Engine>
while these solutions are cleaner, but I found the change required is too disruptive. What we need is a stop-gap solution for now, thus, I decide to add a new helper macro called ENG_DISPATCH. Now within each extension, features are first written as macros like:
Apply2VoltagesImpl<Engine>(Engine*)
which are used internally by:
Apply2Voltages()
by calling:
ENG_DISPATCH(Apply2VoltagesImpl)
// or ENG_THREAD_DISPATCH(Apply2VoltagesImpl, threadId)
This is not pretty but it significantly reduces code duplication. Using this macro, it allows me to remove 917 lines of code and would significantly simplify future programming, which will be implemented later this year.
In the long run, the proper solution should probably be converting all Extensions classes to templates. But that is left for the future.
In openEMS, all extensions are subclasses from the abstract
Engine_Extension
to implement features likeEngine_Extension::Apply2Voltages()
. When anEngine_Extension
is created, it accepts a pointer toEngine
. Simulation data is taken from theEngine
using virtual functions likeEngine::GetVolt()
.Because virtual functions prevent the compiler from inlining the code, in order to select the non-virtual functions, each extension repeats the same simulation code repeated many times using non-virtual subclass engine functions in a big if/else check, e.g. 2 different
Apply2Voltages()
, one callsEngine::GetVolt()
, another callsEngine_sse::GetVolt()
. This led to code duplication and poor readability.I found it's extremely difficult to do any development within these Extensions due to the code duplication problem. I've already tried 2 solutions:
Engine_Extension
classes to a templateEngine_Extension<typename Engine>
Engine_Extension
class into a static Curiously Recurring Template Pattern (CRTP)while these solutions are cleaner, but I found the change required is too disruptive. What we need is a stop-gap solution for now, thus, I decide to add a new helper macro called
ENG_DISPATCH
. Now within each extension, features are first written as macros like:which are used internally by:
by calling:
This is not pretty but it significantly reduces code duplication. Using this macro, it allows me to remove 917 lines of code and would significantly simplify future programming, which will be implemented later this year.
In the long run, the proper solution should probably be converting all Extensions classes to templates. But that is left for the future.