virtual method callbacks in C++11/14/17? - c++11

I have some subscription function that will call my callback when something happens. (Let's say it's a timer, and will pass me an object when a certain number of milliseconds elapses.) The thing I want to be called is a virtual method. I feel std::function and std::bind or lambdas are part of the solution.
The C++99 approach I've used until now involves one-line C functions that know how to call a virtual method. The subscription function takes the C function and a void* user data as arguments. For example:
class Foo {
virtual void OnTimerA( Data* pd );
};
void OnTimerACB( Data* pd, void* pvUserData ) {
( (Foo*) pvUserData )->OnTimerA( pd );
}
/* Inside some method of Foo; 1000 is a number of milliseconds to call me back in;
second arg is a function pointer; third is a void* user data that is passed back
to the C callback. */
SubscribeToTimerOld( 1000, OnTimerACB, this );
What I'm hoping for is a way to write:
SubscribeToTimerNew( 1000, OnTimerA );
or something similar, at least that disposes of the need to write that one-line C binding callback.
I have a feeling that SubscribeToTimerNew()'s argument is probably a std:function of some sort and instead of merely writing OnTimerA I'd have to write something with std::bind to get the this pointer in there.
Alternatively to bind, perhaps a lambda is the way to do it? This compiles, though I dont see how to extend it to let the event handler pass an argument to OnTimerA(). (My linker isn't currently working so don't know if it links or runs as desired.)
SubscribeTimer( 1000, [this](){this->OnTimerA();} );
To mention one alternative I've discarded: give Foo a superclass with a method called OnTimer() that will be called when the timer goes off. Now SubscribeTimer() only need take an elapsed time. I don't like this as it doesn't cleanly allow for multiple timers to be registered. If it did you could give them (say) integer timer ID's and implement OnTimer() as a switch but this seems to be a lot more complicated than the C++99 solution.
Ultimately of the (I assume) several approaches, are there any trade-offs (e.g., heap use) in addition the most obvious question of how much typing is involved? (This is a high-performance application and I'd prefer to minimize or eliminate heap usage.)

C++11, C++14 and C++17 are quite different, especially when it comes to lambdas. And lambdas are a great way to create callbacks. For instance, see Why use std::bind over lambdas in C++14?
Using modern C++, you can use std::function as your callback type and then you can use any callable stuff as an actual callback. Quote from https://en.cppreference.com/w/cpp/utility/functional/function:
Class template std::function is a general-purpose polymorphic function
wrapper. Instances of std::function can store, copy, and invoke any
Callable target -- functions, lambda expressions, bind expressions, or
other function objects, as well as pointers to member functions and
pointers to data members.
Example:
#include <functional>
#include <iostream>
using Callback = std::function<void(int)>;
void subscribe(Callback callback, int duration) {
callback(duration);
}
struct Foo {
void operator()(int duration) {
std::cout << __PRETTY_FUNCTION__ << ' ' << duration << '\n';
}
};
struct Bar {
virtual void myFunction(int duration) {
std::cout << __PRETTY_FUNCTION__ << ' ' << duration << '\n';
}
};
void freeFunction(int duration) {
std::cout << __PRETTY_FUNCTION__ << ' ' << duration << '\n';
}
struct Zorg {
static void staticFunction(int duration) {
std::cout << __PRETTY_FUNCTION__ << ' ' << duration << '\n';
}
};
int main() {
Foo foo;
subscribe(foo, 128);
Bar bar;
auto lambda = [&bar](int duration) {
bar.myFunction(duration);
};
subscribe(lambda, 256);
subscribe(freeFunction, 512);
subscribe(Zorg::staticFunction, 1024);
}
Output:
void Foo::operator()(int) 128
virtual void Bar::myFunction(int) 256
void freeFunction(int) 512
static void Zorg::staticFunction(int) 1024

Related

Boost asio post with shared ptr passed as argument with std::move

I am new to boost:asio. I need to pass shared_ptr as argument to handler function.
E.g.
boost::asio::post(std::bind(&::function_x, std::move(some_shared_ptr)));
Is using std::move(some_shared_ptr) correct? or should I use as below,
boost::asio::post(std::bind(&::function_x, some_shared_ptr));
If both are correct, which one is advisable?
Thanks in advance
Regards
Shankar
Bind stores arguments by value.
So both are correct and probably equivalent. Moving the argument into the bind is potentially more efficient if some_argument is not gonna be used after the bind.
Warning: Advanced Use Cases
(just skip this if you want)
Not what you asked: what if function_x took rvalue-reference arguments?
Glad you asked. You can't. However, you can still receive by lvalue reference and just move from that. because:
std::move doesn't move
The rvalue-reference is only there to indicate potentially-moved-from arguments enabling some smart compiler optimizations and diagnostics.
So, as long as you know your bound function is only executed once (!!) then it's safe to move from lvalue parameters.
In the case of shared-pointers there's actually a little bit more leeway, because moving from the shared-ptr doesn't actually move the pointed-to element at all.
So, a little exercise demonstrating it all:
Live On Coliru
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
static void foo(std::shared_ptr<int>& move_me) {
if (!move_me) {
std::cout << "already moved!\n";
} else {
std::cout << "argument: " << *std::move(move_me) << "\n";
move_me.reset();
}
}
int main() {
std::shared_ptr<int> arg = std::make_shared<int>(42);
std::weak_ptr<int> observer = std::weak_ptr(arg);
assert(observer.use_count() == 1);
auto f = std::bind(foo, std::move(arg));
assert(!arg); // moved
assert(observer.use_count() == 1); // so still 1 usage
{
boost::asio::io_context ctx;
post(ctx, f);
ctx.run();
}
assert(observer.use_count() == 1); // so still 1 usage
f(); // still has the shared arg
// but now the last copy was moved from, so it's gone
assert(observer.use_count() == 0); //
f(); // already moved!
}
Prints
argument: 42
argument: 42
already moved!
Why Bother?
Why would you care about the above? Well, since in Asio you have a lot of handlers that are guaranteed to execute precisely ONCE, you can sometimes avoid the overhead of shared pointers (the synchronization, the allocation of the control block, the type erasure of the deleter).
That is, you can use move-only handlers using std::unique_ptr<>:
Live On Coliru
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
static void foo(std::unique_ptr<int>& move_me) {
if (!move_me) {
std::cout << "already moved!\n";
} else {
std::cout << "argument: " << *std::move(move_me) << "\n";
move_me.reset();
}
}
int main() {
auto arg = std::make_unique<int>(42);
auto f = std::bind(foo, std::move(arg)); // this handler is now move-only
assert(!arg); // moved
{
boost::asio::io_context ctx;
post(
ctx,
std::move(f)); // move-only, so move the entire bind (including arg)
ctx.run();
}
f(); // already executed
}
Prints
argument: 42
already moved!
This is going to help a lot in code that uses a lot of composed operations: you can now bind the state of the operation into the handler with zero overhead, even if it's bigger and dynamically allocated.

Does emplace_back construct an object in its new location instead of using a move?

From this link it states
For example, in the code that we began with, my_vec.push_back("foo")
constructs a temporary string from the string literal, and then moves
that string into the container, whereas my_vec.emplace_back("foo")
just constructs the string directly in the container, avoiding the
extra move. For more expensive types, this may be a reason to use
emplace_back() instead of push_back(), despite the readability and
safety costs, but then again it may not. Very often the performance
difference just won’t matter
So I decided to try that and this is what i did
class foo
{
public:
int counter;
foo()
{
std::cout << "Regular constructor\n";
}
foo(const foo& f)
{
std::cout << "Copy constructor\n";
}
foo(foo&& f)
{
std::cout << "Move constructor\n";
}
};
int main()
{
std::vector<foo> f;
f.push_back(foo()); //Regular constructor and Move Constructor
f.emplace_back(foo()); //Regular constructor and Move Constructor
}
I noticed that both push_back and emplace_back behave similarly. I was thinking that emplace_back will only be calling the regular constructor based on what I read since it will be constructed in the vector stack.
vector::emplace_back(Args&&...) takes the arguments of the constructor you want to construct your new object with. In your quoted example this is const char* for the constructor string::string(const char*). In your own code you're forcing the move constructor by passing a temporary object. To default-construct your object in-place use f.emplace_back() without any arguments as the default constructor takes none.
Also to avoid reallocation (potentially more moves that would spoil your test) ensure the vector has space for your two test objects first using f.reserve(2).
Full code:
class foo
{
public:
foo()
{
std::cout << "Default constructor\n";
}
foo(const foo& f)
{
std::cout << "Copy constructor\n";
}
foo(foo&& f)
{
std::cout << "Move constructor\n";
}
};
int main()
{
std::vector<foo> f;
f.reserve(2);
f.push_back(foo());
f.emplace_back();
}
Output is
Default constructor
Move constructor
Default constructor

std::string::assign vs std::string::operator=

I coded in Borland C++ ages ago, and now I'm trying to understand the "new"(to me) C+11 (I know, we're in 2015, there's a c+14 ... but I'm working on an C++11 project)
Now I have several ways to assign a value to a string.
#include <iostream>
#include <string>
int main ()
{
std::string test1;
std::string test2;
test1 = "Hello World";
test2.assign("Hello again");
std::cout << test1 << std::endl << test2;
return 0;
}
They both work. I learned from http://www.cplusplus.com/reference/string/string/assign/ that there are another ways to use assign . But for simple string assignment, which one is better? I have to fill 100+ structs with 8 std:string each, and I'm looking for the fastest mechanism (I don't care about memory, unless there's a big difference)
Both are equally fast, but = "..." is clearer.
If you really want fast though, use assign and specify the size:
test2.assign("Hello again", sizeof("Hello again") - 1); // don't copy the null terminator!
// or
test2.assign("Hello again", 11);
That way, only one allocation is needed. (You could also .reserve() enough memory beforehand to get the same effect.)
I tried benchmarking both the ways.
static void string_assign_method(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code inside this loop is measured repeatedly
for (auto _ : state) {
str.assign(base, 9);
}
}
// Register the function as a benchmark
BENCHMARK(string_assign_method);
static void string_assign_operator(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code before the loop is not measured
for (auto _ : state) {
str = base;
}
}
BENCHMARK(string_assign_operator);
Here is the graphical comparitive solution. It seems like both the methods are equally faster. The assignment operator has better results.
Use string::assign only if a specific position from the base string has to be assigned.

C++11 chrono library - How to execute method after a specific time interval?

I want to use properly the chrono library to configure my class to call a method, after some milliseconds.
#include <iostream>
#include <chrono>
#include <ctime>
Class House
{
private:
//...
public:
House() {};
~House() {};
void method1() { std::cout << "method1 called" << std::endl; };
void method2() { std::cout << "method2 called" << std::endl; };
void method3() { std::cout << "method3 called" << std::endl; };
};
int main
{
House h;
//For the object 'h', I need to call method1() after 100ms
// ???
//For the object 'h', I need to call method2() after 200ms
// ???
//For the object 'h', I need to call method3() after 300ms
// ???
return 0;
}
Any ideas how to do this?
This is a snippet from a book I have been reading / studying since I'm just getting into C++. (I started about 3 months ago but before that I practiced Java and Python a bit.) This explains how to do what you're intending to do as well as an example to show. I could have explained it in my own words; however I feel as if this hits the nail on the head:
5.3.4.1 Waiting for Events
Sometimes, a thread needs to wait for some kind of external event, such as another thread completing a task or a certain amount of time having passed. The simplest “event” is simply time passing. Consider:
auto t0 = high_resolution_clock::now();
this_thread::sleep_for(milliseconds{20});
auto t1 = high_resolution_clock::now();
cout << duration_cast<nanoseconds>(t1 - t0).count() << " nanoseconds passed\n";
Note that I didn't even have to launch a thread; by default, this_thread refers to the one and only thread (§ 42.2.6). I used duration_cast to adjust the clock’s units to the nanoseconds I wanted. See § 5.4.1 and § 35.2 before trying anything more complicated than this with time. The time facilities are found in <chrono>.
— The C++ Programming Language 4th Edition by Bjarne Stroustrup
I feel as if using this method would help accomplish what you're trying to do: accomplish tasks one after the other. Check out <chrono>. I found this answer because of a book I was reading, this isn't my work this is from a book. If you are intending on having many tasks running simultaneously, you will need to create threads and if they happen to share a resource, you will probably need locks or just use unique_lock / lock_guard. I prefer unique_lock.

Run a function when number of references decrease in shared_ptr

I am developing a cache and I need to know when an object expired.
Is possible run a function when the reference counter of a shared_ptr decrease?
std::shared_ptr< MyClass > p1 = std::make_shared( MyClass() );
std::shared_ptr< MyClass > p2 = p1; // p1.use_count() = 2
p2.reset(); // [ run function ] p1.use_count() = 1
You can't have a function called every time the reference count decreases, but you can have one called when it hits zero. You do this by passing a "custom deleter" to the shared_ptr constructor (you can't use the make_shared utility for this); the deleter is a callable object which is responsible for being passed, and deleting, the shared object.
Example:
#include <iostream>
#include <memory>
using namespace std;
void deleteInt(int* i)
{
std::cout << "Deleting " << *i << std::endl;
delete i;
}
int main() {
std::shared_ptr<int> ptr(new int(3), &deleteInt); // refcount now 1
auto ptr2 = ptr; // refcount now 2
ptr.reset(); // refcount now 1
ptr2.reset(); // refcount now 0, deleter called
return 0;
}
You can specify a deleter functor when creating the shared_ptr. The following article show an example use of a deleter:
http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
Not using a vanilla std::shared_ptr, but if you only require customized behaviour when calling reset() (with no arguments), you can easily create a custom adapter:
template <typename T>
struct my_ptr : public std::shared_ptr<T> {
using std::shared_ptr<T>::shared_ptr;
void reset() {
std::shared_ptr<T>::reset(); // Release the managed object.
/* Run custom function */
}
};
And use it like this:
my_ptr<int> p = std::make_shared<int>(5);
std::cout << *p << std::endl; // Works as usual.
p.reset(); // Customized behaviour.
Edit
This answer is meant to suggest a solution to an issue that I didn't think the other answers did address, that is: executing custom behaviour every time when the refcount is decreased by use of reset().
If the issue is simply to make a call upon object release, then use a custom deleter functor as suggested in the answers by #Sneftel and #fjardon.

Resources