Passing shared_ptr to std::function (member function) - c++

The following observer class registers a callback function with a subject via a call to attach when its ctor executes. I would like the observer's dtor to unregister the callback function.
How do I pass the same pointer to detach as I did to attach so that the subject can remove it from its list of observers?
I'm thinking I have to store a shared_ptr to this but I'm not sure how I get from that to the shared_ptr to the member function callback.
Can anyone help?
Observer::Observer(Subject& subject) : m_subject(subject),
{
m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}
Observer::~Observer()
{
// I tried this initially but realised that the pointer below
// is different to the one passed to `attach` from the ctor.
m_subject.detach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}
void Observer::callback()
{
// do some stuff
}
attach and detach are declared as follows:
void Subject::attach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);
void Subject::detach(const std::string& command, const std::shared_ptr<std::function<void()>>& callback);

I would suggest to also store a copy of the shared_ptr in your observer class, as a member perhaps. Then you could you it to give the same pointer to detach.
Like this:
class Observer {
//Other Stuff here
private:
std::shared_ptr<std::function<void()>> callback_ptr;
};
Observer::Observer(Subject& subject) :
m_subject(subject),
callback_ptr(std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this))
{
m_subject.attach("cmd", std::make_shared<std::function<void()>>(std::bind(&Observer::callback, this)));
}
Observer::~Observer()
{
m_subject.detach("cmd", callback_ptr));
}
It's worth noting that, as #dkg also mentioned, make_shared does always return a new shared_ptr for every time it's called, because it's purpose is to "create a new object with the following parameters and return a shared_ptr to it". Is roughly equivalent to shared_ptr(new std::function<void()> (std::bind(&Observer::callback, this)).
The reason why there is an extra make_shared function is to minimize allocations and to guarantee exception safety in a long expression.
If you just want to shared one object, then just distribute a copy of your shared_ptr.

Each time you call std::make_shared it allocates and constructs a new object for you.
In your code, you call it twice, then you have two instances of your object that are not the same.
You could call it once and keep the shared pointer as a member of your class.

Related

Is there a way to detect if object instance is deleted (in lambda)?

I have this small template function to store my callback function for later "callback".
std::function<void(std::string)> stored_callback;
template<class ReadFileCallback, typename Object, class ...T>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback, Object* object, T ...params) {
std::cout << "fileMgr_ReadWithCallback is processing file: " << filename << std::endl;
stored_callback= [=](std::string s) {
(object->*callback)(s, params...);
};
}
void calledLater() {
stored_callback("somestring");
}
I'm using it from a class like this:
void MyClass::Read() {
fileMgr_ReadWithCallback("myfile", &MyClass::ReadResult, this, fileId);
}
This works nicely, but I have a terrible fear that it can cause a real mess if object gets invalidated (goes out of scope).
As MyClass can be put onto heap:
MyClass* c=new MyClass();
c->Read(); // callback stored
delete c; // c invalidated
calledLater(); // ???
If I try running this, it does not cause any error. But if something overwrites c's former space, it would cause a terrible UB. Or I'm mistaken?
Is there any way when c is deleted for either of these:
not call the stored_callback, or
not call (object->*callback)(s, params...);
Is this good for storing a weak_ptr?
stored_callback = [=](std::string s) {
std::weak_ptr<Object> obj = object; //or std::make_shared?
if (auto spt = obj.lock()) (spt->*callback)(s, params...);
};
Is there a way to detect if object instance is deleted
Yes, so long as you manage its lifetime with shared_ptr, and optionally track it with weak_ptr when you don't want to extend that lifetime.
There is no general way to do this for "unmanaged" objects, meaning those allocated and managed directly via raw pointers, or locals with automatic scope.
You can't detect whether the object still exists via a raw pointer, because if it was deleted or went out of scope, dereferencing the pointer is illegal in the first place. So, you must either
write your code to not destroy the object while the raw pointer exists (ie, static correctness)
not use raw pointers and instead use a smart pointer (most likely shared_ptr and weak_ptr) to control the object's lifetime
have the object somehow detach itself from callbacks when it is destroyed (which is intrusive, as now each object that could be used in a callback needs to know about it)

System.AccessViolationException error when stored callback is executed

I have passed as callback a C++ member function to a C# project through a C++/CLI wrapper (this works fine). The C# project is going to call this delegate when receiving data from another .exe process: an event will be raised and a method will call this callback. So, I needed to "save" this Action delegate using an static instance of a C# class already created. I got the following code:
// C++ unmanaged function
WRAPPER_API void dispatchEvent(std::function<void(int)> processEvent)
{
Iface::Wrapper wrapper;
wrapper.callback = &processEvent;
wrapper.PassCallback();
}
//C++ Managed
public ref class Wrapper
{
public:
std::function<void(int)>* callback;
void ReturnToCallback(int data)
{
(*callback)(data);
}
void PassCallback()
{
StartGenerator^ startGen = gcnew StartGenerator(gcnew Action<int>(this, &Wrapper::ReturnToCallback));
}
};
// C#
public class StartGenerator
{
private Communication comm;
public StartGenerator(Action<int> callback)
{
comm = Communication.Instance;
comm.callback = callback;
}
}
If I call the Action delegate in StartGenerator method, the C++ function is properly executed. However, my goal was saving the delegate to be able to call it afterwards, when data is received from another .exe process. When this data arrives, an event is raised and callback is called from the event method. It is at this point when I get the following exception:
Unhandled Exception: System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other
memory is corrupt. at
Iface.Wrapper.ReturnToCallback(Int32 data)
I think I need to manage the lifetime of the std::function, I don't know about the lifetime of the function object being pointed to by the managed class. The object seems to be deleted and the managed class is left holding a dangling pointer.
I think I need to manage the lifetime of the std::function
Yes, I told you as much when I told you to store a pointer in the managed wrapper, here
I don't know about the lifetime of the function object being pointed to by the managed class.
The std::function is a native object and follows the native C++ rules. Putting a pointer in a managed wrapper won't make it garbage-collected.
The object seems to be deleted and the managed class is left holding a dangling pointer.
Yes, your terminology isn't exact but you've correctly diagnosed the problem. Take a look:
void dispatchEvent(std::function<void(int)> processEvent)
{
Iface::Wrapper wrapper;
wrapper.callback = &processEvent;
wrapper.PassCallback();
}
processEvent is function argument, a std::function object passed by value. The copy made and stored in the argument lives until the end of scope. It has automatic storage duration. When the function returns, all the local variables, function arguments included, are destroyed (not "deleted").
You will need to dynamically allocate (a copy of) the std::function object, like:
typedef std::function<void(int)> cbfn;
wrapper.callback = new cbfn(processEvent);
Now you have a memory leak, but at least you aren't using the object after it's destroyed. If you only make a handful of these objects the leak might even be acceptable. In general, you should implement IDisposable on your wrapper and have the Dispose method do delete callback;. In C++/CLI you use destructor syntax to accomplish that.
~Wrapper()
{
delete callback;
callback = nullptr;
}

How to keep alive a shared_ptr-object of which members are used in an asynchronous function?

Imagine the following code:
void async(connection *, std::function<void(void)>);
void work()
{
auto o = std::make_shared<O>();
async(&o->member, [] { do_something_else(); } );
}
async will, for example, start a thread using member of o which was passed as a pointer. But written like this when o is going out of scope right after async() has been called and it will be deleted and so will member.
How to solve this correctly and nicely(!) ?
Apparently one solution is to pass o to the capture list. Captures are guaranteed to not be optimized out even if not used.
async(&o->member, [o] { do_something_else(); } );
However, recent compilers (clang-5.0) include the -Wunused-lambda-capture in the -Wextra collection. And this case produces the unused-lambda-capture warning.
I added (void) o; inside the lamdba which silences this warning.
async(&o->member, [o] {
(void) o;
do_something_else();
});
Is there are more elegant way to solve this problem of scope?
(The origin of this problem is derived from using write_async of boost::asio)
Boost.Asio seems to suggest using enable_shared_from_this to keep whatever owns the "connection" alive while there are operations pending that use it. For example:
class task : std::enable_shared_from_this<task> {
public:
static std::shared_ptr<task> make() {
return std::shared_ptr<task>(new task());
}
void schedule() {
async(&conn, [t = shared_from_this()]() { t->run(); });
}
private:
task() = default;
void run() {
// whatever
}
connection conn;
};
Then to use task:
auto t = task::make();
t->schedule();
This seems like a good idea, as it encapsulates all the logic for scheduling and executing a task within the task itself.
I suggest that your async function is not optimally designed. If async invokes the function at some arbitrary point in the future, and it requires that the connection be alive at that time, then I see two possibilities. You could make whatever owns the logic that underlies async also own the connection. For example:
class task_manager {
void async(connection*, std::function<void ()> f);
connection* get_connection(size_t index);
};
This way, the connection will always be alive when async is called.
Alternatively, you could have async take a unique_ptr<connection> or shared_ptr<connection>:
void async(std::shared_ptr<connection>, std::function<void ()> f);
This is better than capturing the owner of connection in the closure, which may have unforeseen side-effects (including that async may expect the connection to stay alive after the function object has been invoked and destroyed).
Not a great answer, but...
It doesn't seem like there's necessarily a "better"/"cleaner" solution, although I'd suggest a more "self descriptive" solution might be to create a functor for the thread operation which explicitly binds the member function and the shared_ptr instance inside it. Using a dummy lambda capture doesn't necessarily capture the intent, and someone might come along later and "optimize" it to a bad end. Admittedly, though, the syntax for binding a functor with a shared_ptr is somewhat more complex.
My 2c, anyway (and I've done similar to my suggestion, for reference).
A solution I've used in a project of mine is to derive the class from enable_shared_from_this and let it leak during the asynchronous call through a data member that stores a copy of the shared pointer.
See Resource class for further details and in particular member methods leak and reset.
Once cleaned up it looks like the following minimal example:
#include<memory>
struct S: std::enable_shared_from_this<S> {
void leak() {
ref = this->shared_from_this();
}
void reset() {
ref.reset();
}
private:
std::shared_ptr<S> ref;
};
int main() {
auto ptr = std::make_shared<S>();
ptr->leak();
// do whatever you want and notify who
// is in charge to reset ptr through
// ptr->reset();
}
The main risk is that if you never reset the internal pointer you'll have an actual leak. In that case it was easy to deal with it, for the underlying library requires a resource to be explicitly closed before to discard it and I reset the pointer when it's closed. Until then, living resources can be retrieved through a proper function (walk member function of Loop class, still a mapping to something offered by the underlying library) and one can still close them at any time, therefore leaks are completely avoided.
In your case you must find your way to avoid the problem somehow and that could be a problem, but it mostly depends on the actual code and I cannot say.
A possible drawback is that in this case you are forced to create your objects on the dynamic storage through a shared pointer, otherwise the whole thing would break out and don't work.

Best practice to destroy class object from the thread started from this's objecs's method

So, so the title sounds mad, I think code will provide better understanding for my question
class Class
{
public:
static void* thread_func(void *thisObject)
{
// do some work
delete thisObject; // cleanup
}
start_thread()
{
auto worker = std::thread(thread_func, this);
worker.detach();
}
};
How to use this class
Class *p = new Class;
p->start_thread(); // start some work in parralel and return from function
So, I need to delete allocated object after thread_func is done. What is best way to implement such behaviour? Deleting thisObject from thread function as shown in the code sample works well, but looks as bad practice.
You can't really do that. For one thing, you haven't prevented anyone from stack-allocating an instance of your class. You could do that, but it may just lead to more issues.
Instead, make your thread function simply delete internal resources held in the class. But not the instance of the class. If you need to, you can split your class in two--one to manage deletion of the other which holds the real state.
As you are using c++11, use a lambda - then don't need to worry about anything..
class foo
{
public:
void run() {
// Do something..
}
};
int main(void) {
foo f;
// construct and run the thread...
auto t = std::thread([&f]() { f.run(); });
}
Allocation and deallocation shouldn't be the responsibility of two separate entities, worst in two separate threads. We like to see news and deletes in a symmetric way. Better then, you should use smart pointers:
class Class
{
static void* thread_func(std::shared_ptr<Class> self)
{
// do some work
}
public:
static void start_thread(std::shared_ptr<Class> self)
{
auto worker = std::thread(thread_func, self);
worker.detach();
}
};
How to use this class:
{
Class::start_thread(new Class);
}
Simply deleting object in worker thread is a bad idea, because your thread does not know how object was allocated: int could be created using new, by plcament new in malloced memory, by some allocator, on stack, in static memory, etc.
You can add a callback parameter to your thread_func. In your use-case you will simply pass a fucntion which deletes object. But if the need arises, you can pass fucntions doing anything you want.
I think this is a good place to use std::shared_ptr and in the scope where you are creating the object, use a std::weak_ptr.
http://en.cppreference.com/w/cpp/memory/weak_ptr

Getting shared_ptr to call a member function once its reference count reaches 0

I'm creating a wrapper for a HANDLE that does not work with DuplicateHandle, so instead I am trying to wrap the handle in a shared_ptr.
Imagine the following code:
class CWrapper
{
public:
CWrapper() :
m_pHandle(new HANDLE, &CWrapper::Close)
{
//code to open handle
}
private:
void Close()
{
//code to close handle
}
std::shared_ptr<HANDLE> m_pHandle;
}
I have also tried creating close with a HANDLE parameter (not ideal). Either way, I get the compiler error "Term does not evaluate to a function taking 0 arguments". Is this because of the implicit this pointer? How do I fix this? How do I call a member function from the shared pointer?
You can't call a member function but you can use a custom deleter that is a global function like so:
void my_deleter(Foo *ptr)
{
delete ptr;
std::cout<< "using custom deleter" <<std::endl;
}
shared_ptr<Foo> pf (new Foo, my_deleter);
I think you have your abstractions the wrong way around.
shared_ptr gives you a copyable "handle" to a shared resource that can't itself be copied. Using shared_ptr with a type that doesn't perform its own cleanup when it is deleted isn't an optimal use.
If make your class' single responsibility to clean up this inherently non-copyable resource properly in its destructor, then you can use shared_ptr to provide shared ownership which is what its single responsibility should be. (I consider HANDLE to be non-copyable as if you try to make a simple copy of a HANDLE the copies cannot be treated as independent; the last copy must be correctly closed so the owners of copies would need to know about other copies in existence.)
class CWrapper
{
public:
CWrapper()
{
// code to open handle
}
~CWrapper()
{
// code to close handle
}
private:
// prevent copying
CWrapper(const CWrapper&);
CWrapper& operator=(const CWrapper&);
HANDLE mHandle;
};
Now use shared_ptr<CWrapper> where you need to shared the handle, you can use a typedef if you think that this is too verbose.
A custom deleter is an overly complex solution, IMHO.
If you need to access non-static members from within Close you need to bind its this argument properly
CWrapper() :
m_pHandle(new HANDLE, boost::bind(&CWrapper::Close, this, _1)) {
//code to open handle
}
This, however contains a hidden bug. Your object is copyable, and you bind the deleter to the object of *this. The handle is associated with the first wrapper you create, but if you copy the wrapper, the handle is shared but associated with the first wrapper, which may not exist anymore:
CWrapper getWrapper() { CWrapper w; return w; }
CWrapper x = getWrapper();
After that code was executed and x is going to be destroyed, behavior is undefined because x's destruction of the internal handle pointer will try to use the object bound in w's constructor invokation - however that object doesn't exist anymore!
A solution to this can be to store the data associated with the handle in the allocated object itself, instead of trying to store it in the toplevel handle object, like in the following code
class CWrapper
{
public:
CWrapper():m_pHandle(new CHandle)
{ }
private:
// This class cannot be copied
class CHandle : boost::noncopyable {
friend class CWrapper;
CHandle()
:m_pHandle(new HANDLE) {
// code to open handle
}
~CHandle() {
// code to close this handle, making use of
// auxilary data for whatever reason
}
private:
boost::scoped_ptr<HANDLE> m_pHandle;
// auxilary data associated with the handle...
};
boost::shared_ptr<CHandle> m_pHandle;
};
The auxilary data is not not stored in the handle anymore, but together with the data that's shared among all copy of the wrapper. The shared data itself is created and destroyed using its normal constructor and destructor.
CWrapper getHandle() { return myHandle; }
CWrapper w = getHandle();
The last wrapper going out of life will destroy the handle, which is explicitly shared among all wrappers.
I haven't tested it, but based on the idea presented by shoosh, you may be able to pass a member function like this:
void Class::myDeleteMember(Foo *ptr)
{
delete ptr;
std::cout<< "using custom deleter" <<std::endl;
}
shared_ptr<Foo> pf (new Foo, boost::bind(&Class::myDeleteMember, _1));
Look for deleter in boost::shared_ptr docs. I couldn't find a direct link to it, but basically it is a functor that is called when the ref is 0.