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);
}
Related
I have a 3rd party API that has a function that takes a function pointer as an argument (sample types):
// defined in "Api.h"
typedef int (*Callback) (int x);
unsigned char ApiCall(int p, Callback cb);
int ApiCall(int p, Callback cb) {
return cb(p);
}
And I'm trying interact with this API using a class instance method; here's a sample class:
class ApiWrapper {
public:
int ApiCallback(int x) { return this->factor_ * x; }
static int WorkingApiCallback(int x) { return 3 * x; }
ApiWrapper(int f) { this->factor_ = f; }
private:
int factor_;
}
And a main function to test:
#include <iostream>
#include <functional>
int main() {
ApiWrapper a(2);
using std::placeholders::_1;
std::function<int(int)> lambda = std::bind( &ApiWrapper::ApiCallback, a, _1 );
std::cout << "Class: " << a.ApiCallback(21) << std::endl;
std::cout << "Lambda: " << lambda(21) << std::endl;
std::cout << "Static ApiCall:" << ApiCall(21, ApiWrapper::WorkingApiCallback) << std::endl;
// NOT WORKING
std::cout << "Static ApiCall:" << ApiCall(21, lambda) << std::endl;
std::cout << "Static ApiCall:" << ApiCall(21, this.ApiCallback) << std::endl;
return 0;
}
Is there a way to achieve this without using the static member; as I need to associate/use state each time the callback is invoked by the 3rd party lib.
Online Runnable Source: https://ideone.com/7nVSi8
Thanks!
You are going to have to somehow associate a non-member with the function pointer, as it does not take any sort of context argument. You are going to have a non-member function at some point, no way around that. And that function cannot be a capturing lambda.
One option is to have a (possibly thread local) global pointer that holds the instance.
i.e. you do:
myType * glbInst;
..void someFunc()
{
myType myInst;
glbInst = &myInst;
apiCall([] (int) glbInst->member(x); });
}
Another option is to use libffi's closure system to create a function at run-time and have the instance be part of the saved data. I use this pattern very often but it's a bit complicated to paste here.
Is there a way to achieve this without using the static member;
There's a hackish solution.
Define a non-member function.
Store a pointer to an object that can be accessed by the non-member function.
Call the member function of the object from the non-member function.
ApiWrapper* objectForCallback = NULL;
int NonMemberFunction(int x)
{
assert(objectForCallback != NULL);
return objectForCallback->ApiCallback(x);
}
and the setup for the above to work:
ApiWrapper a(2);
objectForCallback = &a;
Now you can use:
std::cout << "Static ApiCall:" << ApiCall(21, NonMemberFunction) << std::endl;
I'm trying to program a simple but flexible event system (mostly just as an exercise, I know there are existing libraries that have really good event handlers), and I've run into a little stumbling block.
How can you check if an std::function that's a delegate (probably through a lambda, possibly though std::bind) is a valid function/if the object for the member function still exists before calling it? I've tried simply using std::function's bool operator, but haven't had any success.
Ideally I'd like to A. do the checking somewhere other than inside the delegate function, and B. still have the code be valid when the std::function that's being checked isn't a delegate.
Any ideas?
Edit: Here's the source for the test that I ran
#include <iostream>
#include <string>
#include <functional>
class Obj {
public:
std::string foo;
Obj(std::string foo) : foo(foo) {}
std::function<void()> getDelegate() {
auto callback = [this]() {this->delegatedFn();};
return callback;
}
void delegatedFn() {
std::cout << foo << std::endl;
}
};
int main() {
Obj* obj = new Obj("bar");
std::function<void()> callback = obj->getDelegate();
callback();
delete obj;
//perform some type of check here whether function is valid, without needing to know whether the function is a delegate or not
if(callback) {
std::cout << "Callback is valid" << std::endl; //callback is still considered valid after obj is deleted
callback(); //no exception thrown, prints a random series of characters
}
else {
std::cout << "Callback is invalid" << std::endl;
}
return 0;
}
You can use smart pointers (std::shared_ptr/std::weak_ptr) instead of naked ones:
#include <iostream>
#include <string>
#include <functional>
#include <memory>
class Obj {
public:
std::string foo;
Obj(std::string foo) : foo(foo) {}
void delegatedFn() {
std::cout << foo << std::endl;
}
};
int main() {
auto obj = std::make_shared<Obj>("bar");
std::weak_ptr<Obj> ptr = obj;
std::function<void()> callback = [ptr](){
auto sh = ptr.lock();
if(sh) { std::cout << "valid" << std::endl; sh->delegatedFn(); }
else { std::cout << "invalid" << std::endl; }
};
callback();
obj = nullptr;
callback();
return 0;
}
In this case you are not directly checking the validity of a std::function (that is valid when you assign it something, even if that something captures a dangling pointer).
Instead, you check that the referred object is still alive from within the function itself.
The broadcaster/listener pattern I use looks like this:
template<class...Args>
struct broadcaster {
std::vector< std::weak_ptr< std::function<void(Args...)> > > callbacks;
void operator()(Args...args) const {
std::remove_erase_if( begin(callbacks), end(callbacks), [](auto&& ptr){return !ptr;} );
auto tmp = callbacks;
for (auto pf : tmp) {
if (pf && *pf) (*pf)(args...);
}
}
std::shared_ptr<void> listen( std::shared_ptr<std::function<void(Args...)>> f ) {
callbacks.push_back(f);
return f;
}
std::shared_ptr<void> listen( std::function<void(Args...)> f ) {
auto ptr = std::make_shared<std::function<void(Args...)>>(std::move(f));
return listen(ptr);
}
};
Listeners to a message .listen their callback with broadcaster. They get back a shared_ptr<void> token.
So long as that token exists, the broadcaster will send messages at the function object passed in.
Obj would either store a std::vector<std::shared_ptr<void>> tokens or a single std::shared_ptr<void>. When it was destroyed, its listeners would automatically deregister.
Alternatively, Obj could inherit from shared_from_this. Then it implements
std::function<void()> delegate;
std::shared_ptr<std::function<void()>> getDelegatedFn() {
if (!delegate) delegate = [this]{ this->delegateFn(); }
return {
&delegate,
shared_from_this()
};
}
which shares the lifetime of the Obj instance itself (uses the aliasing constructor of shared_ptr). Pass this to listen and done.
Is this the correct way to use std smart pointers to ensure ptr safety
This example may not be the best, but I am trying to emulate some real code. The problem I had was in the real code, the communicator pointer was a raw pointer which could be de-allocated at any moment - resulting in a crash in using the pointer.
So I decided to look into std::shared_ptr and std::weak_ptr to see how it should be designed now we have C++11. I use a weak_ptr in the sending code which checks if the ptr is still valid and only then will dereference the ptr. Is this code the correct approach? Any improvements?
#include <memory>
#include <iostream>
#include <string>
class communicator
{
public:
communicator(const char* name, int comport, int speed) : name_(name), comport_(comport), speed_(speed) { }
void send(const std::string& s) {
std::cout << "sending " << s << " using " << name_ << " at " << speed_ << " rate and using com port " << comport_ << '\n';
}
private:
const char* name_;
int comport_;
int speed_;
};
class sender
{
public:
sender() {}
void set_communicator(std::weak_ptr<communicator> comms) {
comms_ = comms;
}
void send(const std::string& s)
{
if (auto sh = comms_.lock())
sh->send(s);
else
std::cout << "Attempting to send: " << s << " but ptr no longer exists\n";
}
private:
std::weak_ptr<communicator> comms_;
};
int main() {
sender mysender;
{
// create comms object
std::shared_ptr<communicator> comms(new communicator("myname", 3, 9600));
mysender.set_communicator(comms);
mysender.send("Hi guys!");
} // comms object gets deleted here
mysender.send("Hi guys after ptr delete!");
}
Output:
sending Hi guys! using myname at 9600 rate and using com port 3
Attempting to send: Hi guys after ptr delete! but ptr no longer exists
pointer which could be de-allocated at any moment - resulting in a
crash in using the pointer
That's the symptom behind the rationale for a introducing a weak_ptr; thus I'd consider your weak_ptr - based approach right.
What I find debatable, however, is that in conjunction with this
sender() : comms_() {}
void set_communicator(std::weak_ptr<communicator> comms) {
comms_ = comms;
}
sort-of two-phase construction of the the sender 's internal asset comms_
you don't reset the internal asset's state to after-construction-state once lock() fails in
void send(const std::string& s)
But that's not "wrong" by itself; it's just something that could be considered for the full scale app.
The other thing is that you don't throw (or let throw by the shared_ptr(weak_ptr) ctor (#11)) when lock() fails, but just if-else handle that. I cannot know the requirements of your full-scaled app, but based on the extract you assembled, exception based error handling would improve the design imo.
E.g.:
#include <memory>
#include <stdexcept>
#include <iostream>
#include <string>
class communicator
{
public:
communicator(const char* name, int comport, int speed)
: name_(name), comport_(comport), speed_(speed) { }
void send(const std::string& s) {
std::cout << "sending " << s << " using " << name_ << " at "
<< speed_ << " rate and using com port " << comport_
<< '\n';
}
private:
const char* name_;
int comport_;
int speed_;
};
class sender
{
public:
struct invalid_communicator : public std::runtime_error {
invalid_communicator(const std::string& s) :
std::runtime_error(
std::string("Attempting to send: \"") + s
+ "\" but communicator is invalid or not set"
) {}
};
sender() : comms_() {}
void set_communicator(std::weak_ptr<communicator> comms) {
comms_ = comms;
}
/* non-const */
void send(const std::string& s) throw (invalid_communicator)
{
try {
auto sh = std::shared_ptr<communicator>(comms_);
sh->send(s);
} catch (const std::bad_weak_ptr& e) {
comms_ = decltype(comms_)();
throw invalid_communicator(s);
}
}
private:
std::weak_ptr<communicator> comms_;
};
int main() {
int rv = -1;
sender mysender;
for (auto com : {1, 2, 3}) {
try {
{
// create comms object
auto comms = std::make_shared<communicator>(
"myname", com, 9600
);
mysender.set_communicator(comms);
mysender.send("Hi guys!");
}// comms object gets deleted here
mysender.send("Hi guys after ptr delete!");
// never reached in this example; just to illustrate
// how the story could continue
rv = EXIT_SUCCESS;
break; // it'd be not nice to "break", but I did not want to
// introduce another state variable
} catch (const sender::invalid_communicator& e) {
std::cerr << e.what() << std::endl;
}
}
return rv;
}
live a Coliru's
Is this the correct way to use std smart pointers to ensure ptr safety
in addition to what has been mentioned by decltype_auto, I can just add that the reason for using weak_ptr is amongst others are to prevent cyclic dependencies. You might as well make it shared if that possibility does not exist, which would make the implementation of send less error prone, except if the lifetime of the communication chanel is really temporary.
You could hide the fact that their exists various connections or sessions in the implementation.
Also, when designing interfaces/APIs with the standard smart pointers, consider use of the more restricted pointers like unique_pointer.
Such a pointer communicates intent very clearly - e.g. by taking a unique pointer as argument to a function, you clearly tell the user that he is surrendering ownership of the pointed-to resource to the called function.
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.
I have a void function inside of a class. In old C++ i'd make a function static taking the class name as a parameter and had my own class which took a static void function + a void* for me to easily call it.
However that feels old school. It also isn't templated which feels like i could be doing more. What is a more modern way of creating callbacks to myclassVar.voidReturnVoidParamFunc
Use std::function and lambdas (or std::bind()) to store callables:
#include <functional>
#include <iostream>
class Test
{
public:
void blah() { std::cout << "BLAH!" << std::endl; }
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test;
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // often clearer -and not more expensive- than std::bind()
callback();
}
Result:
BLAH!
BIM!
BOUM!
BLAH!
Compiles and run: http://ideone.com/T6wVp
std::function can be used as any copyiable object, so feel free to store it somewhere as a callback, like in object's member. It also means that you can freely put it in standard containers, like std::vector< std::function< void () > > .
Also note that equivalent boost::function and boost::bind have been available for years.
For an example of passing in parameters to a C++ 11 callback using Lambda's and a vector, see http://ideone.com/tcBCeO or below:
class Test
{
public:
Test (int testType) : m_testType(testType) {};
void blah() { std::cout << "BLAH! " << m_testType << std::endl; }
void blahWithParmeter(std::string p) { std::cout << "BLAH1! Parameter=" << p << std::endl; }
void blahWithParmeter2(std::string p) { std::cout << "BLAH2! Parameter=" << p << std::endl; }
private:
int m_testType;
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test(7);
//std::function< void() > callback = std::bind( &Test::blah, test );
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // might be clearer than calling std::bind()
callback();
// example of callback with parameter using a vector
typedef std::function<void(std::string&)> TstringCallback;
std::vector <TstringCallback> callbackListStringParms;
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter(tag); });
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter2(tag); });
std::string parm1 = "parm1";
std::string parm2 = "parm2";
int i = 0;
for (auto cb : callbackListStringParms )
{
++i;
if (i == 1)
cb(parm1);
else
cb(parm2);
}
}