How to call method of wrapped object by unique_ptr? - c++

I'm able to compile the following code where I pass a "callback" to an object (Table). What I'm trying to do now is inside Table, call the handle method defined in EventListener
#include <iostream>
#include <vector>
#include <memory>
class Table {
public:
struct Listener{
virtual void handle(int i) = 0;
};
std::vector<std::unique_ptr<Listener>> listeners_;
void add_listener(std::unique_ptr<Listener> l){
listeners_.push_back(std::move(l));
}
};
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
int main(int argc, char** argv)
{
Table table;
std::unique_ptr<EventListener> el;
table.add_listener(std::move(el));
return 0;
}
EDIT ****
This is what Im trying inside Table. It results in a segmentation fault:
for (auto t =0; t < (int)listeners_.size(); ++t) {
listeners_[t]->handle(event);
}

It doesn't work because you never created an object for it to be called on, just a pointer. The pointer inside the vector will be nullptr and therefore calling the function on it will crash. unique_ptr has absolutely nothing to do with this problem.
Half the problem is that Table cannot handle nullptr but doesn't check for it, and the other half the problem is that Table cannot handle nullptr but main passes one in anyway.
The iteration code is not the problem at all.

As mentioned in the answer by Puppy the line
std::unique_ptr<EventListener> el;
creates an empty std::unique_ptr. This causes the code for nivoking the
listeners to later dereference a nullptr.
A simple fix for your example is to create a listener and use that
when creating the unique_ptr:
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
// in main()
std::unique_ptr<NoOpListener> el{ new NoOpListener };
table.add_listener(std::move(el));
As mentioned in the comments your code should ensure that nullptr
isn't allowed. One way of doing this would be to add a check for
nullptr in add_listener and throw an exception or silently ignore
them. The first option is the better solution of the two as it
signals the caller that something is wrong.
But I don't see why you would store listeners in std::unique_ptrs.
The use for std::unique_ptr is for ownership. I do not see why the
observed instance should own the listeners. There is another alternative
that I think is better; use std::function<>() and pass it by value.
This disallows the use of nullptr and has the added bonus of accepting
not only function objects, but also normal functions and lambdas as shown
in the following code:
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
class Table {
public:
std::vector<std::function<void(int)>> listeners_;
void add_listener(std::function<void(int)> l) {
listeners_.push_back(l);
}
void invoke_listeners(int event)
{
for(auto l : listeners_) {
l(event);
}
}
};
struct NoOpListener {
void operator() (int i) {
std::cout << "NoOpListener::operator()(" << i << ")" << std::endl;
}
};
void cb(int i) {
std::cout << "cb(" << i << ")" << std::endl;
}
int main(int argc, char** argv)
{
Table table;
table.add_listener(NoOpListener{});
table.add_listener(cb);
table.add_listener([](int i) { std::cout << "[lambda](" << i << ")" << std::endl; });
table.invoke_listeners(10);
return 0;
}
NOTE: As you can see I also used the C++11 ranged-for construct for iterating
over the listeners.

Related

How to safely use callbacks when the bound function could be deleted

In the following code, we are creating an object, bind one function and call it before then after deleting the object.
This obviously leads to a segmentation fault as the underlying object was used after deletion.
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
You can test at cpp.sh/5ubbg
#include <memory>
#include <functional>
#include <iostream>
class CallbackContainer {
public:
std::string data_;
CallbackContainer(std::string data): data_(data) {}
~CallbackContainer() {}
void rawTest(const std::string& some_data);
};
void CallbackContainer::rawTest(const std::string& some_data) {
std::cout << data_ << " " << some_data << std::endl;
}
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
auto callback = std::bind(&CallbackContainer::rawTest, container.get(), std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
Returns:
> Internal data Before
> 0x7178a3bf6570
> 0x7178a3bf6570
> Error launching program (Segmentation fault)
If you can share ownership, do this:
int main(int /* argc */, char const** /* argv */) {
std::shared_ptr<CallbackContainer> container; // shared pointer
container.reset(new CallbackContainer("Internal data"));
// shared with functor
auto callback = std::bind(&CallbackContainer::rawTest, container, std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
If not, you should somehow pass invalidity to function object explicitly.
This assumes that you know when container is deleted, and manually invalidate explicitly before that:
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
std::atomic<CallbackContainer*> container_raw(container.get());
auto callback = [&container_raw] (std::string data)
{
if (auto c = container_raw.load())
c->rawTest(data);
};
callback("Before");
std::cout << &callback << std::endl;
container_raw.store(nullptr);
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
For asio cases, usually shared_from_this() is used, like std::bind(&MyClass::MyMemFunc, shared_from_this(), ptr);
The way I prefer while working with boost asio:
I faced the same issue while working with boost asio. We need to register callbacks to io_service and it was difficult to implement some sort of Manager class which manages lifetime of the objects we may create.
So, I implement something that was suggested by Michael Caisse in cppcon2016. I started passing the shared_ptr to the object to the std::bind.
I used to extend the lifetime of the object and in the callback, you can decide to either extend the lifetime of the object again (by registering the callback again) or let it die automatically.
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
auto func = std::bind(&MyClass::MyMemFunc, this, ptr);
ptr.reset();
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
I wouldn't say that's the best solution but using by my above approach, you can detect if you need to proceed further in your callback or not.
It might not be the efficient way but it won't cause any undefined behavior.
void CallbackContainer::rawTest(const std::string& some_data, std::shared<CallbackContainer> ptr)
{
if (ptr.use_count() == 1) {
// We are the only owner of the object.
return; // and the object dies after this
}
std::cout << data_ << " " << some_data << std::endl;
}
EDIT:
An example code that shows how to do it using std::enable_shared_from_this:
#include <iostream>
#include <memory>
#include <functional>
class ABCD: public std::enable_shared_from_this<ABCD> {
public:
void call_me_anytime()
{
std::cout << "Thanks for Calling Me" << std::endl;
}
public:
ABCD(void)
{
std::cout << "CONSTRUCTOR" << std::endl;
}
~ABCD(void)
{
std::cout << "DESTRUCTOR" << std::endl;
}
};
int main(void)
{
auto ptr = std::make_shared<ABCD>();
auto cb = std::bind(&ABCD::call_me_anytime, ptr->shared_from_this());
ptr.reset();
std::cout << "RESETING SHARED_PTR" << std::endl;
std::cout << "CALLING CALLBACK" << std::endl;
cb();
std::cout << "RETURNING" << std::endl;
return 0;
}
Output:
CONSTRUCTOR
RESETING SHARED_PTR
CALLING CALLBACK
Thanks for Calling Me
RETURNING
DESTRUCTOR
As a followup, we decided to use roscpp method which is similar to Alex Guteniev's proposition.
Instead of doing std::bind explicitly, we use it internally and keep the parent as std::weak_ptr<const void> pointer to the std::shared_ptr<P> (as it would conflict with unique_ptr).
The API looks like:
std::shared_ptr<Container> container;
queue.subscribe(&Container::callback_method, container);
The subscription function is as following with T the explicit type of the data (Class-wise) but P the implicit class of the Parent class (Container in this case).
template <class P>
std::shared_ptr<ThreadedQueue<T>> subscribe(void (P::*function_pointer)(std::shared_ptr<const T>), std::shared_ptr<P> parent, size_t queue_size = -1) {
callback_ = std::bind(function_pointer, parent.get(), std::placeholders::_1);
parent_ = std::weak_ptr<const void>(parent);
}
When calling the callback, we do the following check:
if(auto lock = parent_.lock()) {
callback_(data);
}

Any techniques or tricks to modifying existing functions in C++?

Within JavaScript, you can pull off something like this:
function bunny() { alert("The bunny jumped."); }
var oldBunny = bunny;
function bunny() {
oldBunny();
alert("The bunny also ran.");
}
bunny(); // The bunny Jumped. The bunny also ran.
As one can see, the old "bunny" function had code appended to it by copying to a variable, then recreating the function with the same name. The copy of the original function runs, and the new code also runs.
I wish to replicate a similar mechanic in C++.
Now before you have a meltdown and start explaining the differences between static and dynamic languages, I get it. I'm not looking for something identical to what's provided, but I do desire something similar.
Furthermore, I'm not trying to do this to modify existing code; I wish to format my own source code to allow such a mechanic for other users to take advantage of.
One of the first ideas I had was to perhaps setup various macros within the code that could later be modified by other files.
Another idea would be to create a Signal and Slots system like in QT. Though I have no clue how to do such a thing myself.
Thank you for reading; I hope you have some suggestions.
Well, if you recognize which feature of JavaScript functions makes this possible, it's not too hard to do the same in C++. In JavaScript functions also have closures, which regular function in C++ don't have. But C++ lambdas are of a closure type. And if one defines bunny to be something which can both hold an object of a closure type, and be reassigned, you're all set.
The C++ standard library offers a nice default choice for this, in the form of std::function. We can just re-write your original JavaScript as follows:
std::function<void()> bunny = [] {
std::cout << "The bunny jumped.\n";
};
auto oldBunny = std::move(bunny);
bunny = [oldBunny] {
oldBunny();
std::cout << "The bunny also ran.\n";
};
bunny();
You can use functors.
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string operator ()()
{
return "Base call";
}
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual std::string operator()()
{
return "Wrapper: " + Base::operator()();
}
};
int main()
{
Base* pFun = new Base;
std::cout << "Now check Base: " << (*pFun)() << std::endl;
delete pFun;
pFun = new Derived;
std::cout << "Now check Derived: " << (*pFun)() << std::endl;
return 0;
}
Assuming the goal is to allow the calling code to extend the program's functionality beyond what the initial code provided, I might use a user-updatable array of functor-objects, something like this:
#include <iostream>
#include <memory>
class Function
{
public:
virtual void Call() = 0;
};
typedef std::shared_ptr<Function> FunctionSharedPointer;
class OldBunny : public Function
{
public:
virtual void Call()
{
std::cout << "The bunny jumped." << std::endl;
}
};
class NewBunny : public Function
{
public:
NewBunny(FunctionSharedPointer oldFunction) : _oldFunction(oldFunction) {/* empty */}
virtual void Call()
{
_oldFunction->Call();
std::cout << "The bunny also ran." << std::endl;
}
private:
FunctionSharedPointer _oldFunction;
};
enum {
FUNCTION_BUNNY,
// other functions could be declared here later...
NUM_FUNCTIONS
};
// Our table of functions that the user can Call() if he wants to
static FunctionSharedPointer _functionTable[NUM_FUNCTIONS];
// Wrapper function, just to keep users from accessing our table directly,
// in case we ever want to change it to something else
void CallFunction(int whichFunction)
{
_functionTable[whichFunction]->Call();
}
// Another wrapper function
void SetFunction(int whichFunction, FunctionSharedPointer newFunctionDefinition)
{
_functionTable[whichFunction] = newFunctionDefinition;
}
// And another
FunctionSharedPointer GetFunction(int whichFunction)
{
return _functionTable[whichFunction];
}
int main(int argc, char ** argv)
{
// Our default function values get set here
SetFunction(FUNCTION_BUNNY, std::make_shared<OldBunny>());
std::cout << "before:" << std::endl;
CallFunction(FUNCTION_BUNNY);
// Now let's update an entry in our function table to do something different!
FunctionSharedPointer op = GetFunction(FUNCTION_BUNNY);
FunctionSharedPointer np = std::make_shared<NewBunny>(op);
SetFunction(FUNCTION_BUNNY, np);
std::cout << "after:" << std::endl;
CallFunction(FUNCTION_BUNNY);
return 0;
}
void bunny()
{
cout << "The bunny jumped." << endl;
}
void oldBunny()
{
bunny();
}
void newBunny()
{
bunny();
cout << "The bunny also ran." << endl;
}
#define bunny newBunny
int main()
{
bunny();
return 0;
}
If you don't need oldBunny(), just remove it.

C++11 rvalue calls destructior twice

I'm trying to make a class runner (run a class at a fixed time freq), which runs a class in another thread, and can be controlled (like pause, resume, stop) from main thread.
So I want to take advantage of C++11's Functor and other features. But I have a strange problem, the Functor's destructor passed into Runner has been called twice.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
class Runner {
public:
typedef function<bool()> fn_t;
Runner(fn_t &&fn) : fn_(move(fn)), thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
fn_t fn_;
thread thread_;
static void Thread(Runner &runner) {
while (runner.fn_()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliumseconds(1));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (++count < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
Fn fn;
Runner runner(move(fn));
return 0;
}
outpus:
Fn
Runner
~Fn
~Runner
Running
Running
Running
Running
Running
~Fn
~Fn
and if I change
Fn fn;
Runner runner(move(fn));
to
Runner runner(Fn());
the program outpus nothing and stalls. I have tried to disable compiling optimization, nothing changes. Any explanation?
How can I fix this or do the samething in other method? Should I implement this class like std::async / std::thread?
Update to Runner runner(Fn())
This statement was interrupted as a function declaration.
Runner runner((Fn())) solved problem.
Thanks for all comments and answers. After look into rvalue, seems I have misunderstand the meaning of rvalue reference from ground 0. I will try some other ways.
Final Solution for this problem
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
using namespace std;
template<typename T, typename... Args>
class Runner {
public:
Runner(Args&&... args) :
t(forward<Args>(args)...),
thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
T t;
thread thread_;
static void Thread(Runner &runner) {
while (runner.t()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliseconds(100));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (count++ < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
//vector<Fn> fns;
//fns.emplace_back(Fn());
Runner<Fn> runner;
return 0;
}
outpus:
Fn
Runner
~Runner
Running
Running
Running
Running
Running
~Fn
Use std::move:
Runner(fn_t &&fn) : fn_(std::move(fn)), thread_(Thread, ref(*this)) {
/*....*/
}
You need to explicitly use std::move, otherwise it will be treated as a const reference. You could also use std::forward:
Runner(fn_t &&fn) : fn_(std::forward<fn_t>(fn)), thread_(Thread, ref(*this)) {
/*....*/
}
First of all, you shouldn't be taking r-value reference arguments for the most part, except in your own move constructors. As you have it, there is no way to pass l-values of std::function<bool()> into the constructor of Runner.
int main()
{
Fn fn;
std::function<bool()> func(fn);
Runner runner(func); // this is illegal
}
Maybe I'm just not creative enough, but I can't imagine any valid reason which you would want to prevent such a thing.
You should let std::function take care of its own copying/moving. When you need a copy of an object, take your parameter by value. If the function is passed an r-value, then it will be move constructed. If it is passed an l-value, then it will be copy constructed. Then, in your Runner constructor, you can move the value into the member object, as fontanini showed.
None of this is guaranteed to reduce destructor calls though, because when you move an object, you're still creating a second object, and will have to destroy a second object. In order to see fewer destructions, copy elision would have to happen, which actually does avoid the creation of multiple objects. But unlike moving, that's an implementation issue that's not guaranteed to come into effect in all the situations where you would hope.

temporary object in range-based for

I know that in general the life time of a temporary in a range-based for loop is extended to the whole loop (I've read C++11: The range-based for statement: "range-init" lifetime?). Therefore doing stuff like this is generally OK:
for (auto &thingy : func_that_returns_eg_a_vector())
std::cout << thingy;
Now I'm stumbling about memory issues when I try to do something I thought to be similar with Qt's QList container:
#include <iostream>
#include <QList>
int main() {
for (auto i : QList<int>{} << 1 << 2 << 3)
std::cout << i << std::endl;
return 0;
}
The problem here is that valgrind shows invalid memory access somewhere inside the QList class. However, modifying the example so that the list is stored in variable provides a correct result:
#include <iostream>
#include <QList>
int main() {
auto things = QList<int>{} << 1 << 2 << 3;
for (auto i : things)
std::cout << i << std::endl;
return 0;
}
Now my question is: am I doing something dumb in the first case resulting in e.g. undefined behaviour (I don't have enough experience reading the C++ standard in order to answer this for myself)? Or is this an issue with how I use QList, or how QList is implemented?
Since you're using C++11, you could use initialization list instead. This will pass valgrind:
int main() {
for (auto i : QList<int>{1, 2, 3})
std::cout << i << std::endl;
return 0;
}
The problem is not totally related to range-based for or even C++11. The following code demonstrates the same problem:
QList<int>& things = QList<int>() << 1;
things.end();
or:
#include <iostream>
struct S {
int* x;
S() { x = NULL; }
~S() { delete x; }
S& foo(int y) {
x = new int(y);
return *this;
}
};
int main() {
S& things = S().foo(2);
std::cout << *things.x << std::endl;
return 0;
}
The invalid read is because the temporary object from the expression S() (or QList<int>{}) is destructed after the declaration (following C++03 and C++11 ยง12.2/5), because the compiler has no idea that the method foo() (or operator<<) will return that temporary object. So you are now refering to content of freed memory.
The compiler can't possibly know that the reference that is the result of three calls to operator << is bound to the temporary object QList<int>{}, so the life of the temporary is not extended. The compiler does not know (and can't be expected to know) anything about the return value of a function, except its type. If it's a reference, it doesn't know what it may bind to. I'm pretty sure that, in order for the life-extending rule to apply, the binding has to be direct.
This should work because the list is no longer a temporary:
#include <iostream>
#include <QList>
int main() {
auto things = QList<int>{};
for (auto i : things << 1 << 2 << 3)
std::cout << i << std::endl;
return 0;
}
And this should work because the binding is direct, so the rule can apply:
#include <iostream>
#include <QList>
int main() {
for (auto i : QList<int>{1, 2, 3})
std::cout << i << std::endl;
return 0;
}

inheritance problem

I've messed up something.
Here is the code:
#include <iostream>
class connection_c {
private:
std::string data_;
void (*saveCallBack_)();
public:
connection_c(std::string &data) : data_(data) { std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;}
void registerCallBack(void(*cb)()) { saveCallBack_ = cb; }
};
class inst_c {
private:
static int id;
connection_c conn;
static void cb() { std::cout << __FUNCTION__ << " id = " << id << std::endl; }
public:
inst_c(connection_c &c, int a) : conn(c), id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
conn.registerCallBack(&cb);
}
};
class group_inst_c {
private:
connection_c conn;
inst_c i,j,k;
public:
group_inst_c(std::string data) : conn(data), i(conn,1), j(conn,2), k(conn,3) {}
};
int main() {
group_inst_c gi("asdf");
return 0;
}
What I want to achieve ;)
create a group of instances (group_inst_c)
it should initialize single connection for the group (connection_c)
each instance (inst_c) should use this connection (it will be serialized)
.. in addition each instance should register separate callback
For sure I've messed up with cloning, but I guess probably not only.
Can someone help me solve this puzzle? thx.
Your code creates a copy of your connection object for each instance. The original connection object is then only accessible by your group_inst_c. Is this what you want? If not, you need to change:
class inst_c {
private:
static int id;
connection_c& conn; // <-- Needs to be a reference.
in addition each instance should register separate callback
I'm not sure what you mean here. Are the callbacks supposed to be member functions? Then you need to use a "pointer to member function" (the ::*, .*, and ->* operators). If the callbacks are supposed to be regular functions, you should be okay with your current code. You'll just need to add this to class connection_c:
void doCallback(void) { (*saveCallBack_)(); }
If I understood that correctly (you want to call several callbacks from a single connection [object]), you need a list in connection_c to register the callbacks (just like delegates in C# if you know them).
If an event occurs to this connection, it has to know where to report. So you have to iterate through the callbacks somehow (call them one by one; you cannot call them all at once). The easiest, straightforward way is to use an STL list or maybe boost offers something appropriate.
Take a look at this: A C++ delegate class. In the main function, there's a vector defined that takes multiple callbacks. You could use this pattern in you connection_c class to add and not set a callback.
Try to keep it simple at first. There's always an opportunity to grow/improve the design later on. Below is some example code and here are a couple of things I was thinking about while building it:
1) As mentioned, keep it simple. For example, maybe the group concept can be a vector (i.e. inst_group_t) to start. You can always grow the design later as you learn more about it.
2) Try to reduce class dependencies. For example, maybe I do not need to have the connection as a member variable. I can pass it in when its needed (i.e. execute()). Maybe the callback doesn't need to be registered (i.e. execute()), since its 1 connection_c to many inst_c instances registering a callback for each inst_c would mean connection would have some container. Keep it simple :)
3) Try to use const and reference as much as possible (i.e. connection_c constructor). Less copy constructors/temp objects will be created.
#include <iostream>
class connection_c {
private:
std::string data_;
public:
connection_c(const std::string &data) : data_(data) {
std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;
}
};
class inst_c {
private:
int id;
public:
inst_c(int a) : id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
}
typedef void (*execute_callback_t)(int i);
void execute(connection_c& connection, execute_callback_t callback) {
callback(id);
}
};
void mycallback(int id) {
std::cout << "Instance number " << id << " executed" << std::endl;
}
int main() {
typedef std::vector<inst_c*> inst_group_t;
inst_group_t group;
std::string data;
connection_c connection(data);
for (int i = 0; i < 10; ++i)
group.push_back(new inst_c(i) );
for (int i = 0; i < 10; ++i)
group[i]->execute(connection, mycallback);
for (int i = 0; i < 10; ++i)
delete group[i];
return 0;
}