How to implement zero-overhead Inversion of Control - c++

Almost every OOP programmer has been exposed to the concept of Inversion of control. In C++, we can implement that principle with dynamic callbacks (i.e. functors such as lambdas and function pointers). But if we know at compile time what procedure we are to inject into the driver, theoretically I believe that there is a way to eliminate the overhead of function passing and invoking by composing the callbacks and the driver/signal/what-so-ever function into an "unrolled procedure". Here is an example.
For a GUI program, we have logic on window 1) setup, 2) loop, and 3) termination. We can inject code 1) after window setup, 2) in each render loop, 3) and before termination. A procedural approach is to write in this manner:
// Snippet 1:
init_window();
init_input_handler();
init_canvas();
init_socket();
while (!window_should_close()) {
update_window();
handle_input();
draw_on_canvas();
send_through_socket();
}
drop_input_handler();
drop_canvas();
drop_socket();
terminate_window();
OOP programmers pride ourselves in decoupling and proper abstraction. Instead, we write this:
// Snippet 2:
init_window();
on_window_init_signal.send();
while (!window_should_close()) {
update_window();
on_render_signal.send();
}
on_exit_signal.send();
terminate_window();
But this brings an unwanted overhead as said above. My question is: How can we utilize the C++ metaprogramming mechanisms to achieve zero-overhead inversion of control so that code in a similar form of snippet 2 can be transformed into snippet 1 statically (i.e. at compile time)?
EDIT: I can think of loop optimizations widely found in optimizers. Maybe this is a generalized version of that issue.

"Zero Overhead" & "But if we know at compile time what procedure we are to inject into the driver, " is possible.
You can use a template class to pass the functions to call like that:
struct SomeInjects
{
static void AtInit() { std::cout << "AtInit from SomeInjects" << std::endl; }
static void AtHandleInput() { std::cout << "AtHandleInput from SomeInjects" << std::endl; }
static void AtDraw() { std::cout << "AtDraw from SomeInjects" << std::endl; }
};
struct OtherInject
{
static void AtInit() { std::cout << "AtInit from OtherInject" << std::endl; }
static void AtHandleInput() { std::cout << "AtHandleInput from OtherInject" << std::endl; }
static void AtDraw() { std::cout << "AtDraw from OtherInject" << std::endl; }
};
template < typename Mixin >
struct Win
{
void Init()
{
Mixin::AtInit();
}
void HandleInput()
{
Mixin::AtHandleInput();
}
void Draw()
{
Mixin::AtDraw();
}
};
int main()
{
Win<SomeInjects> wsi;
wsi.Init();
wsi.HandleInput();
wsi.Draw();
Win<OtherInject> wso;
wso.Init();
wso.HandleInput();
wso.Draw();
}
But this has the drawback, that it needs static functions.
More elaborated try:
struct SomeInjects
{
void AtInit() { std::cout << "AtInit from SomeInjects" << std::endl; }
void AtHandleInput() { std::cout << "AtHandleInput from SomeInjects" << std::endl; }
void AtDraw() { std::cout << "AtDraw from SomeInjects" << std::endl; }
};
struct OtherInject
{
void AtInit() { std::cout << "AtInit from OtherInject" << std::endl; }
void AtHandleInput() { std::cout << "AtHandleInput from OtherInject" << std::endl; }
void AtDraw() { std::cout << "AtDraw from OtherInject" << std::endl; }
};
template < typename Mixin >
struct Win: Mixin
{
void Init()
{
this->AtInit();
}
void HandleInput()
{
this->AtHandleInput();
}
void Draw()
{
this->AtDraw();
}
};
int main()
{
Win<SomeInjects> wsi;
wsi.Init();
wsi.HandleInput();
wsi.Draw();
Win<OtherInject> wso;
wso.Init();
wso.HandleInput();
wso.Draw();
}
The last technique is called Mixin.
If your compiler inlines all and everything depends on many things. But typically all calls are inlined if the called functions are not really to big.
But if you need any runtime changeable callbacks, you have to use some kind of callable representation. That can be function pointers or things like std::function. The last generates more or less always some minor overhead.
But remember: A simple dereferenced pointer is typically not the speed problem at all. More important is, that in such cases constants can not be propagated, the code can't be inlined and as a result an overall optimization is not longer possible. But if runtime flexibility is needed, it will have some cost. As always: Measure before optimize!

Related

What are the differences between a template and a function pointer for a Strategy design pattern in C++

I'm implementing a Strategy Design Pattern in c++, and I've found a couple of different options I could take. One route would be to use a template, and might look like this:
namespace Strategies
{
struct IsEven
{
bool doSomething(int x) { return x % 2 == 0; }
};
struct IsOdd
{
bool doSomething(int y) { return y % 2 == 1; }
};
}
template<typename Strategy>
class Processor
{
public:
Processor() : _strat{ Strategy() }
{}
bool process(int num)
{
return _strat.doSomething(num);
}
private:
Strategy _strat;
};
int main()
{
Processor<Strategies::IsEven> templateOne{};
Processor<Strategies::IsOdd> templateTwo{};
std::cout << "Process 4 with One: " << (templateOne.process(4) ? "True" : "False") << std::endl;
std::cout << "Process 4 with Two: " << (templateTwo.process(4) ? "True" : "False") << std::endl;
}
Another route would be to use function pointers, and might look like this:
#include <functional>
class ProcessorTwo
{
public:
using StrategyFunction = std::function<bool(int)>;
static bool lessThanFive(int num) {
return num < 5;
}
static bool greaterThanFive(int num) {
return num > 5;
}
ProcessorTwo(StrategyFunction strat) : _strat{ strat }
{}
bool process(int num) {
return _strat(num);
}
private:
StrategyFunction _strat;
};
int main()
{
ProcessorTwo functionPointerOne{ ProcessorTwo::greaterThanFive };
ProcessorTwo functionPointerTwo{ ProcessorTwo::lessThanFive };
std::cout << "Process 4 with One: " << (functionPointerOne.process(4) ? "True" : "False") << std::endl;
std::cout << "Process 4 with Two: " << (functionPointerTwo.process(4) ? "True" : "False") << std::endl;
}
I will know the functions that will be used at compile time. I'm new enough to c++ that I don't really understand what the differences between these two approaches would be. I've heard function pointers add a layer of indirection, but wouldn't the same also be true of a struct holding the function? Is there a more "idiomatic" c++ option, or does it just come down to developer preference?
The main difference is the template version uses "compile time polymorphism" meaning the selection of the strategy happens at compile time and the strategy is part of the type. Thus, the strategy a particular instance of Processor<T> uses must be known at compile time and cannot be changed dynamically after a Processor<T> is created.
You could add a member function, however, to make it so the strategy used by a ProcessorTwo can be changed dynamically. You could also write, say, a function that takes a std::function<bool(int)> as an argument and creates a ProcessorTwo with it in the function's body; you couldn't do this with a Processor<T> unless it was a function template.
So if you need that kind of dynamism a function pointer or std::function based approach is the way to go, but if you don't need it then the template version will be more efficient because calling the strategy will not involve runtime indirection.

In C++, is it possible to define a function with a varying code block to be executed and passed via another function?

I have a class handling SQL queries (it uses Qt functions, but I think this doesn't matter). All queries that write data have the exact same base frame that looks like this:
bool Database::someSqlFunction(some variables)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
... Code using the passed variables and query ...
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
Is it possible to re-use this code so that it won't have to be defined per function? I thought about using a function to be called with a pointer to the function containing the varying code, but the signature is different for each function and I thus would have to define an overloaded one for each case; I also thought about using the preprocessor to generate the function, but it's the same problem with the different number and type of arguments.
Can a block of code to be executed be passed to another function? Or can this be done via a function template?
Edit: Here's how this can be implemented:
In the header:
template<typename SqlFunction>
bool writeHelper(SqlFunction sqlFunction)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
sqlFunction(query);
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
And and example function using it:
bool Database::registerPlayers(const QString &name, int markerId)
{
return writeHelper([&](QSqlQuery &query) {
queryPrepare(query, QStringLiteral("INSERT INTO players(id, name, marker) "
"VALUES(NULL, ?, ?)"));
query.bindValue(0, name);
query.bindValue(1, markerId != 0 ? markerId : SQLITE_NULL);
queryExec(query);
});
}
Edit 2: The same can also be achieved without templates:
Using std::function, the lambda defined in the actual function can simply be passed without having to use templates. The implementation of the helper function looks like this then:
bool Database::writeHelper(std::function<void(QSqlQuery &query)> sqlFunction)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
sqlFunction(query);
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
Anyway, it's apparently better to use the template approach, as in this case, the compiler will generate the needed functions build-time and can optimize, whereas he doesn't know what will be actually done using the std::function approach, as the calls happen run-time.
Lambda closures seem to be what you need.
https://en.cppreference.com/w/cpp/language/lambda
As an example, generic algorithms are very similar to your use case: a common
algorithm which does not change and some small parts that
can be freely provided at the invocation.
https://en.cppreference.com/w/cpp/header/algorithm
Without knowing the exact details of what is expected,
I provide here a trivial example:
#include <iostream>
template<typename Fnct>
void
common_part(Fnct fnct)
{
std::cout << "begin common part\n";
for(auto i=0; i<3; ++i)
{
std::cout << "iteration " << i << " of common part\n";
fnct(i);
}
std::cout << "end common part\n";
}
void
specific_function_A()
{
common_part(
[&](const auto &n)
{
std::cout << "specific part A: " << n << '\n';
});
}
void
specific_function_B(int something_else)
{
common_part(
[&](const auto &n)
{
std::cout << "specific part B: " << n+something_else << '\n';
something_else*=2;
});
}
int
main()
{
specific_function_A();
std::cout << "~~~~~~~~\n";
specific_function_B(100);
return 0;
}
Even if the signature of the lambda-closure is always the same, the
capture can be seen as a workaround to provide additional parameters.

Code structure for different versions of devices

I am writing a "device driver" (C++14) which can handle multiple versions of protocols meant for different versions of devices. This device driver is running on an external PC which communicates with the device over Ethernet with a HTTP based protocol. There are common functionalities for all versions, but some functions maybe additional in certain versions of the protocol.
Below is an example:
class ProtocolBase {
public:
virtual void reset_parameters() {
std::cout << "reset parameters" << std::endl;
}
virtual void set_parameters() {
std::cout << "set parameters" << std::endl;
}
};
class ProtocolV1 : public ProtocolBase
{
public:
void set_parameters() override {
std::cout << "set parameters for V1" << std::endl;
}
};
class ProtocolV2 : public ProtocolBase
{
public:
void set_parameters() override {
std::cout << "set parameters for V2" << std::endl;
}
void reset_parameters() {
std::cout << "reset parameters for V2" << std::endl;
}
void do_V2() {
std::cout << "doing V2" << std::endl;
}
};
Below is the main:
int main(int argc, char const *argv[])
{
int version = std::atoi(argv[1]);
std::unique_ptr<ProtocolBase> protocol = std::make_unique<ProtocolV1>();
switch (version)
{
case 1:
/* do nothing at the moment */
break;
case 2:
protocol.reset(new ProtocolV2);
break;
default:
break;
}
protocol->reset_parameters();
if(ProtocolV2* p = dynamic_cast<ProtocolV2*>(protocol.get())) { //not sure about this
p->do_V2();
}else {
std::cout << "This functionality is unavailable for this device" << std::endl;
}
protocol->set_parameters();
return 0;
}
I have a feeling using dynamic_cast is not the best way to go here. Looking forward to some feedback.
Edit: As per #Ptaq666's answer, I modified ProtocolBase and ProtocolV2 as:
class ProtocolBase {
public:
virtual void do_V(){
std::cerr << "This functionality is unavailable for this device" << std::endl;
}
};
class ProtocolV2 : public ProtocolBase
{
public:
void do_V() override {
std::cout << "doing V2" << std::endl;
}
};
With this, there's no need for dynamic_cast anymore, though base class will have to know all the functionalities. This seems to be the best solution for now.
Like in most cases when it comes to chose the appropriate system architecture the answer is
"it depends" :). The most comfortable solution would be to introduce protocol-specific behavior
of the ProtocolBase subclasses in their constructors
class ProtocolV2 : public ProtocolBase
{
public:
ProtocolV2::ProtocolV2(args) {
// set some params that will determine when do_V2() is called
// it can be some numeric setting, a callback, or similar
}
void set_parameters() override {
// you can use V2 behavior here maybe?
std::cout << "set parameters for V2" << std::endl;
}
void reset_parameters() override {
// or here maybe?
std::cout << "reset parameters for V2" << std::endl;
}
private:
void do_V2() {
std::cout << "doing V2" << std::endl;
}
};
If for some reason you cannot do this, there is a possibility to keep do_V2() as public
non-virtual method, but to call it before passing ProtocolV2 as a pointer to ProtocolBase
to the sysytem that will use it. Of course the limitation is that do_V2 can only be called outside
your system scope, which might not really solve the problem.
Another option is to actually move do_V2() to the interface:
class ProtocolBase {
public:
virtual void reset_parameters() {
std::cout << "reset parameters" << std::endl;
}
virtual void set_parameters() {
std::cout << "set parameters" << std::endl;
}
virtual void do_V2() {
std::cout << "not supported" << std::endl;
}
};
and implement it as "not supported" behavior by default. Only ProtocolV2 will implement this behavior
as a valid part of the protocol.
In the end, if none of the above is OK, you can of course use the dynamic_cast as you proposed.
Personally I try to avoid dynamic_cast because my office mates will start to abuse it for sure,
but in some cases it is a correct solution.
Also if you decide to cast the pointer, use std::shared_ptr with dynamic_pointer_cast instead of accessing a raw pointer from unique_ptr.
In general it depends on how the derived classes ProtocolV1 and ProtocolV2 are formed and what are the data members and weather if the respective member functions are going to use different data members or not!
The reason is simply since there is no dependency to member data, the member functions are only sensitive to the type of the objects that they have been called with, not their value/state!
It is like having a (non member) function overload like:
void function(ProtocolV1 *){
std::cout << "set parameters for V1" << std::endl;
}
void function(ProtocolV2 *){
std::cout << "set parameters for V2" << std::endl;
}
And then calling it once by a pointer of type ProtocolV1 * and once with null pointer of typeProtocolV2 *.
If you like alternatives for the usage you presented in the question you can even use C-style cast:
The result was the SAME!
Finally if you are going to call the member function to then call another function from it which requires some data member/s ,which is/are different across the derived classes as its argument/s, then you can not use any cast unless you introduce some form of compensation to fill the data that is not presented in the casted type!
Good luck!

A simple signal for a button in C++

I've been looking at a few signal/slot implementations, and with no exception they were pretty complicated, some even relying on MOC and extra code generation, like those of Qt.
I realize there are concerns such as threat safety and whatnot, but for a simple, single threaded scenario, is there something wrong with going for a simple approach, something like:
typedef void (*fPtr)();
class GenericButton
{
public:
GenericButton() : funcitonToCall(nullptr) {}
void setTarget(fPtr target) {
funcitonToCall = target;
}
void pressButton() {
if (funcitonToCall) funcitonToCall();
}
private:
fPtr funcitonToCall;
};
void doSomething(){
std::cout << "doing something..." << std::endl;
}
void doSomethingElse(){
std::cout << "doing something else..." << std::endl;
}
int main(){
GenericButton myButton;
myButton.setTarget(doSomething);
myButton.pressButton();
myButton.setTarget(doSomethingElse);
myButton.pressButton();
}
It is still possible to chain several other methods and pass data in the target void function. So why all the complexity for something as trivial as executing some code when a button gets clicked.
This is a perfectly sensible solution, but don't restrict yourself to just function pointers. Use std::function which allows you to bind things, call member functions on objects, use lambdas and still resort to a function pointer where it makes sense. Example:
#include <iostream>
#include <functional>
using namespace std::placeholders;
class GenericButton
{
public:
typedef std::function<void()> fPtr;
GenericButton() : funcitonToCall(nullptr) {}
void setTarget(fPtr target) {
funcitonToCall = target;
}
void pressButton() {
if (funcitonToCall) funcitonToCall();
}
private:
fPtr funcitonToCall;
};
struct foo {
void doSomething() const {
std::cout << "doing something in a foo..." << std::endl;
}
static void alternative(int i) {
std::cout << "And another, i=" << i << "\n";
}
};
void doSomethingElse() {
std::cout << "doing something else..." << std::endl;
}
int main() {
GenericButton myButton;
foo f;
myButton.setTarget(std::bind(&foo::doSomething, &f));
myButton.pressButton();
myButton.setTarget(doSomethingElse);
myButton.pressButton();
myButton.setTarget(std::bind(foo::alternative, 666));
myButton.pressButton();
myButton.setTarget([](){ std::cout << "Lambda!\n"; });
myButton.pressButton();
}
There's almost always a better solution in C++ than function pointers.
If you don't have std::function/std::bind there's always alternatives in boost that work and you can roll your own std::function alternative without too much work which would be worth doing if you want to make something like this.
Most of the signal/slot mechanisms that are around date from a time when things like boost::bind was not a viable option. Those days are long gone and you can get something standard and more flexible for little more complexity than just a function pointer.

Is it possible to prevent an RAII-style class from being instantiated "anonymously"?

Suppose I have an RAII-style C++ class:
class StateSaver
{
public:
StateSaver(int i) { saveState(); }
~StateSaver() { restoreState(); }
};
...to be used like so in my code:
void Manipulate()
{
StateSaver save(1);
// ...do stuff that modifies state
}
...the goal being to enter some state, do stuff, then leave that state when I leave that scope. Is there a way to make this typo not compile (or warn, or somehow complain so that the mistake can be noticed)?
void Manipulate()
{
StateSaver(1); // ruh-roh, state saved and immediately restored!
// ...do stuff that modifies state
}
I'm not aware of anything in C++ itself which I could use to prevent this, but that doesn't mean it doesn't exist. If there isn't anything in C++, compiler-specific extensions would be acceptable. I'm primarily interested in anything targeting gcc and msvc (someday icc, ideas for other compilers welcome but less likely to be useful) so hacks for any of them would be useful (abstracted into appropriately #ifdef'd macro definitions, of course).
I'm not sure if anything can be done at compile-time. For a run-time check, you could do this:
struct SaveMatrix
{
SaveMatrix(const SaveMatrix& that) {
assert(this == &that);
glPushMatrix();
}
~SaveMatrix() { glPopMatrix(); }
};
Which requires the client to write:
SaveMatrix sm(sm);
and there's no way to do the same for a temporary without binding it to an identifier (at which point it's no different from an auto variable).
SaveMatrix save(); doesn't define an object either. It declares a function.
There's very little you can do to prevent others (or yourself, FTM) from doing something else than they wanted to. The only thing I can think of is not writing the code itself, but writing a macro instead.
#define SAVE_MATRIX SaveMatrix save ## __LINE__
However, this is quite ugly. OTOH, it does catch the error at compile-time.
I actually had to tweak my solution in a bunch of ways from the variant Waldo posted, but what I eventually got to is a macro-ized version of:
class GuardNotifier
{
bool* notified;
public:
GuardNotifier() : notified(NULL) { }
void init(bool* ptr) { notified = ptr; }
~GuardNotifier() { *notified = true; }
};
class GuardNotifyReceiver
{
bool notified;
public:
GuardNotifyReceiver() : notified(false) { }
void init(const GuardNotifier& notifier)
{ const_cast<GuardNotifier&>(notifier).init(&notified); }
~GuardNotifyReceiver() { assert(notified); }
};
class StateSaver
{
GuardNotifyReceiver receiver;
public:
StateSaver(int i,
const GuardNotifier& notifier = GuardNotifier())
{
receiver.init(notifier)
saveState();
}
~StateSaver()
{
restoreState();
}
};
The class can never tell if it was instantiated as a temporary (SaveMatrix()) or as a variable (SaveMatrix save;). I think the best way to stop the programmer doing that without stack or macro hacks is to force a member function call after construction, eg:
class RAII
{
public:
bool valid;
RAII()
: valid(false)
{
cout << "RAII ctor" << endl;
}
void Do()
{
valid = true;
}
~RAII()
{
assert(valid);
cout << "RAII dtor" << endl;
}
};
This then works as follows:
{
// Intended use
RAII raii;
raii.Do();
cout << "Some task" << endl;
}
{
// Woops: forgot Do()
RAII raii;
cout << "Some task" << endl;
}
{
// Woops: forgot Do()
RAII();
cout << "Some task" << endl;
}
{
// Programmer shot self in foot, hopefully the act of typing this would make them realise that
RAII().Do();
cout << "Some task" << endl;
}