Efficient method to pass a callback member function

I am developing a method for an input handler class. Here is some kind of pseudo code ...

void InputHandler::ScanEvents( boost::function1< void, std::string& > &func ) { // Scan keys, determining string to pass // If string found, call func with string as its argument on object tied to func } 

I'm not quite sure how to implement this, or if it is possible, since the whole point of the function is to separate it from the caller. The idea is that the object has a private member function and a boost :: function member that holds it. Whenever it calls ScanEvents on its InputHandler, it passes this function, so ScanEvents can "activate" it with every corresponding event.

Efficiency is a problem because it refers to an area where performance is important, and this feature is often called.

PS I swear I remember reading such an example in one of Scott Meyer's books, but I canโ€™t find it for life. Perhaps it was in Modern C ++ Design ... looking ....

+4
source share
4 answers

Something along the lines

 class Thingy { public: Thingy() : callback(bind(&Thingy::Callback, this, _1)) {} void DoStuff() { handler.ScanEvents(callback); } private: InputHandler handler; function<void(string)> callback; void Callback(string s) { cout << "Called with " << s << endl; } }; 

should do what you describe. But probably it would be more efficient for a callback to take a string by reference.

+2
source

boost::function has a rather slow overhead - about 20ns per call . I would not call it from the inner loop - but I would not call any other function pointer. To call a member function, simply use boost::lambda::bind to create an anonymous wrapper function:

 ih->ScanEvents(boost::lambda::bind(&ThisClass::CallbackFunc, this, boost::lambda::_1)); 

If you really need really high performance, you should use the built-in template function with boost::lambda functor parameter:

 template<typename F> double democaller(const F &f) { double x = 1; for (int i = 0; i < 1000000; i++) { x = f(x); } return x; } namespace l = boost::lambda; void demouser() { std::cout << democaller(l::_1 + 1); } 

With sufficiently high optimization settings, the lambda expression can be embedded in the calling site, completely eliminating the overhead.

+3
source

Perhaps you are looking for a team implementation in Modern C ++ Design.

The boost :: function has as much overhead as needed to do what it does. The goal is to allow you to pass a "pointer" to any function that can respond to its interface. If you do not need this behavior, then these overheads are real costs. If you do this, I honestly don't see a better approach than boost :: function (itโ€™s even optimized to make sure you donโ€™t get a bunch of extra memory usage from virtual functions in some implementations).

You can build a method that will lead to possible inline code, but as soon as you try to save it in a common interface, you will get a boost :: function bonus (possibly more).

What I would recommend is to simply use boost :: function until you find that you really need to replace something faster. Then, and only then do you write the material of the template of varying complexity to make this happen.

Just saving the boost :: function may be sufficient for what you need. You can also see boost :: signals.

+1
source

Usually calling a private method in another class is not a good idea.

You can implement the interface style class and inherit it and write your ScanEvents method for the expected input of this type, for example:

 class Notifyable { public: virtual void notify(std::string s) = 0; }; void InputHandler::ScanEvents( Notifyable &n ) { // Scan keys, determining string to pass // If string found, call func with string as its argument on object tied to func n.notify(<string>); } 

I would think that it could be faster, simply because you avoid any possible overhead with the boost :: function shell.

0
source

Source: https://habr.com/ru/post/1313584/


All Articles