Managing the lifetime of member functions bound by `std::bind` - c++

I am currently experimenting with writing an event queue in C++11. I am using std::bind to obtain std::function objects which are called when certain events happen. The code for this roughly looks like this:
class A
{
public:
void handle();
};
class B { ... };
// Later on, somewhere else...
std::vector< std::function< void() > functions;
A a;
B b;
functions.push_back( std::bind( &A::handle, &a ) );
functions.push_back( std::bind( &B::handle, &b ) );
// Even later:
for( auto&& f : functions )
f(); // <--- How do I know whether f is still "valid"?
Is there any way to guarantee the validity of the function object so that I can avoid stumbling over undefined behaviour here?
I have already taken a look at this question here, std::function to member function of object and lifetime of object, but it only discussed whether deleting a pointer to a bound object raises undefined behaviour. I am more interested in how to handle the destruction of such an object. Is there any way to detect this?
EDIT: To clarify, I know that I cannot guarantee a lifetime for non-static, non-global objects. It would be sufficient to be notified about their destruction so that the invalid function objects can be removed.

As #Joachim has stated, no lifetime is associated to the member function (it's a code section, not data). So you're asking if there is a way to know if the object still exists prior to execute the callback call.
You've to make a sort of framework, where the object dctor notify the container when it is destroyed, so the container could delete it from its "observers", the vector containing all the objects. To do that, the object must memorize in its instance the ptr to the container.
UPDATE
#Jason talks about the use of shared_ptr. It's okay to use them, but in this case, is not addressing the case of HOW to destroy the object linked in other object-notification list. Shared_ptr postponed the destruction of an instance until all "managed" references to it are deleted. But if you need to destroy object A, AND delete all reference to it because that object MUST be deleted, you've to look into all containers that store a shared_ptr and remove it. A very painful activity. The simplest solution (using raw ptr or shared_ptr, if you can use them, is irrelevant) is a two-link connection between the observer and the observed, in such way each one can notify its destruction to the other. How to store this information? many ways to accomplish it: hash tables, slots in observer, etc

One hack/workaround that achieves the desired result would be to use a parameter of type std::shared_ptr. When the bind is destructed, so is the shared pointer - which will do the right thing when it is the last reference. However this involves changes to the signature used. To make it slightly less awkward, you can use static methods that take in a std::shared_ptr this - sort of like the self parameter concept in python, if you are familiar.
Or if you are fine with C++11, you can just use a lambda capture of the shared pointer.
You'd need to dynamically allocate the instances to use this method.

Related

What is the need for enable_shared_from_this? [duplicate]

This question already has answers here:
What is the usefulness of `enable_shared_from_this`?
(6 answers)
Closed 6 years ago.
I am new to C++11 and I came across enable_shared_from_this. I do not understand what it is trying to achieve? So I have a program that uses enable_shared_from_this.
struct TestCase: enable_shared_from_this<TestCase>
{
std::shared_ptr<testcase> getptr() {
return shared_from_this();
}
~TestCase() { std::cout << "TestCase::~TestCase()"; }
};
int main()
{
std::shared_ptr<testcase> obj1(new TestCase);
std::shared_ptr<testcase> obj2 = obj1->getptr();
// The above can be re written as below
// std::shared_ptr<testcase> obj2 = shared_ptr<testcase>(obj1);
}
My question is when I need a pointer to 'this', why not use the obj itself. Why to return a 'this' from a function of that class like using getptr() and then returning shared_from_this()????
I do not understand.
Second question, if enable_shared_from_this is NOT used, why is the dtor called twice that creates a problem, a crash!!!!
Another way I can bypass using enable_shared_from_this is like this.
Add this in class TestCase
std::shared_ptr getptr1(shared_ptr obj) {
return std::shared_ptr(obj);
}
and from main make a call this this:
std::shared_ptr bp2 = bp1->getptr1(bp1);
And done. We do not need enable_shared_from_this. Why on the earth do we need it??
A shared_ptr manages two different things. It has a pointer to its data, and a pointer to a reference counting block.
The reference counting block has a strong counter, a weak counter and a destroy operation in it.
When you std::shared_ptr<X>(pX), it creates a new reference counting block that, when the last (strong) reference goes away, it deletes the pX object.
The same thing happens when you std::shared_ptr<X>(this).
So, if you wrap an object in std::shared_ptr in two different spots, you have to different reference counting blocks, and they both want to destroy the object when they go away.
enable_shared_from_this<X> changes how this works. When you create a shared pointer to an object inheriting from it, it stores a std::weak_ptr<X> inside the enable_shared_from_this<X>. A weak pointer stores a pointer to the above reference counting block, but only "holds" a weak reference (not a strong one).
Then, when you call shared_from_this(), it does a .lock() on that weak pointer and returns a shared pointer using the reference counting block of the old one created (as stored by the weak_ptr).
Now, the above is an example implementation of what it could do: the standard mandates behavior, not implementation, and the weak_ptr is a possible way to implement it. Similarly, the reference counting block detail is just an example implementation.
The core issue is that two independent shared pointers wrapping the same pointer will try to independently manage the pointer's lifetime. enable_shared_from_this makes the first smart pointer's reference counting block be used by later shared_from_this() return values.
Short answer: you need enable_shared_from_this when you need to use inside the object itself existing shared pointer guarding this object.
Out of the object you can simply assign and copy a shared_ptr because you deal with the shared_ptr variable as is. But when you are in one of the class members then if you need to use a shared pointer pointing to self object (instead of ordinary this) and there is no such shared pointer in arguments of that method then shared_from_this() is what will help you.
Using std::make_shared(this) is absolutely unsafe as you can not have two shared pointers on the same object. While, shared_from_this() is safe because it uses weak_ptr to "resolve" already existing shared_ptr.
To be able to use shared_from_this() you must first use enable_shared_from_this in your class definition which adds a shared_from_this() method to your class.
Note, shared_from_this() can not be used in the class constructor! At that time the shared_ptr does not exist yet, so the shared_from_this() can't resolve any exisiting pointers.
And when and why one can need a shared pointer to this instead of just this it is quite other question. For example, it is widely used in asynchronous programming for callbacks binding.

What is the best smart pointer return type for a factory function?

With respect to smart pointers and new C++11/14 features, I am wondering what the best-practice return values and function parameter types would be for classes that have these facilities:
A factory function (outside of the class) that creates objects and returns them to users of the class. (For example opening a document and returning an object that can be used to access the content.)
Utility functions that accept objects from the factory functions, use them, but do not take ownership. (For example a function that counts the number of words in the document.)
Functions that keep a reference to the object after they return (like a UI component that takes a copy of the object so it can draw the content on the screen as needed.)
What would the best return type be for the factory function?
If it's a raw pointer the user will have to delete it correctly which is problematic.
If it returns a unique_ptr<> then the user can't share it if they want to.
If it's a shared_ptr<> then will I have to pass around shared_ptr<> types everywhere? This is what I'm doing now and it's causing problems as I'm getting cyclic references, preventing objects from being destroyed automatically.
What is the best parameter type for the utility function?
I imagine passing by reference will avoid incrementing a smart pointer reference count unnecessarily, but are there any drawbacks of this? The main one that comes to mind is that it prevents me from passing derived classes to functions taking parameters of the base-class type.
Is there some way that I can make it clear to the caller that it will NOT copy the object? (Ideally so that the code will not compile if the function body does try to copy the object.)
Is there a way to make it independent of the type of smart pointer in use? (Maybe taking a raw pointer?)
Is it possible to have a const parameter to make it clear the function will not modify the object, without breaking smart pointer compatibility?
What is the best parameter type for the function that keeps a reference to the object?
I'm guessing shared_ptr<> is the only option here, which probably means the factory class must return a shared_ptr<> also, right?
Here is some code that compiles and hopefully illustrates the main points.
#include <iostream>
#include <memory>
struct Document {
std::string content;
};
struct UI {
std::shared_ptr<Document> doc;
// This function is not copying the object, but holding a
// reference to it to make sure it doesn't get destroyed.
void setDocument(std::shared_ptr<Document> newDoc) {
this->doc = newDoc;
}
void redraw() {
// do something with this->doc
}
};
// This function does not need to take a copy of the Document, so it
// should access it as efficiently as possible. At the moment it
// creates a whole new shared_ptr object which I feel is inefficient,
// but passing by reference does not work.
// It should also take a const parameter as it isn't modifying the
// object.
int charCount(std::shared_ptr<Document> doc)
{
// I realise this should be a member function inside Document, but
// this is for illustrative purposes.
return doc->content.length();
}
// This function is the same as charCount() but it does modify the
// object.
void appendText(std::shared_ptr<Document> doc)
{
doc->content.append("hello");
return;
}
// Create a derived type that the code above does not know about.
struct TextDocument: public Document {};
std::shared_ptr<TextDocument> createTextDocument()
{
return std::shared_ptr<TextDocument>(new TextDocument());
}
int main(void)
{
UI display;
// Use the factory function to create an instance. As a user of
// this class I don't want to have to worry about deleting the
// instance, but I don't really care what type it is, as long as
// it doesn't stop me from using it the way I need to.
auto doc = createTextDocument();
// Share the instance with the UI, which takes a copy of it for
// later use.
display.setDocument(doc);
// Use a free function which modifies the object.
appendText(doc);
// Use a free function which doesn't modify the object.
std::cout << "Your document has " << charCount(doc)
<< " characters.\n";
return 0;
}
I'll answer in reverse order so to begin with the simple cases.
Utility functions that accept objects from the factory functions, use them, but do not take ownership. (For example a function that counts the number of words in the document.)
If you are calling a factory function, you are always taking ownership of the created object by the very definition of a factory function. I think what you mean is that some other client first obtains an object from the factory and then wishes to pass it to the utility function that does not take ownership itself.
In this case, the utility function should not care at all how ownership of the object it operates on is managed. It should simply accept a (probably const) reference or – if “no object” is a valid condition – a non-owning raw pointer. This will minimize the coupling between your interfaces and make the utility function most flexible.
Functions that keep a reference to the object after they return (like a UI component that takes a copy of the object so it can draw the content on the screen as needed.)
These should take a std::shared_ptr by value. This makes it clear from the function's signature that they take shared ownership of the argument.
Sometimes, it can also be meaningful to have a function that takes unique ownership of its argument (constructors come to mind). Those should take a std::unique_ptr by value (or by rvalue reference) which will also make the semantics clear from the signature.
A factory function (outside of the class) that creates objects and returns them to users of the class. (For example opening a document and returning an object that can be used to access the content.)
This is the difficult one as there are good arguments for both, std::unique_ptr and std::shared_ptr. The only thing clear is that returning an owning raw pointer is no good.
Returning a std::unique_ptr is lightweight (no overhead compared to returning a raw pointer) and conveys the correct semantics of a factory function. Whoever called the function obtains exclusive ownership over the fabricated object. If needed, the client can construct a std::shared_ptr out of a std::unique_ptr at the cost of a dynamic memory allocation.
On the other hand, if the client is going to need a std::shared_ptr anyway, it would be more efficient to have the factory use std::make_shared to avoid the additional dynamic memory allocation. Also, there are situations where you simply must use a std::shared_ptr for example, if the destructor of the managed object is non-virtual and the smart pointer is to be converted to a smart pointer to a base class. But a std::shared_ptr has more overhead than a std::unique_ptr so if the latter is sufficient, we would rather avoid that if possible.
So in conclusion, I'd come up with the following guideline:
If you need a custom deleter, return a std::shared_ptr.
Else, if you think that most of your clients are going to need a std::shared_ptr anyway, utilize the optimization potential of std::make_shared.
Else, return a std::unique_ptr.
Of course, you could avoid the problem by providing two factory functions, one that returns a std::unique_ptr and one that returns a std::shared_ptr so each client can use what best fits its needs. If you need this frequently, I guess you can abstract most of the redundancy away with some clever template meta-programming.
What would the best return type be for the factory function?
unique_ptr would be best. It prevents accidental leaks, and the user can release ownership from the pointer, or transfer ownership to a shared_ptr (which has a constructor for that very purpose), if they want to use a different ownership scheme.
What is the best parameter type for the utility function?
A reference, unless the program flow is so convoluted that the object might be destroyed during the function call, in which case shared_ptr or weak_ptr. (In either case, it can refer to a base class, and add const qualifiers, if you want that.)
What is the best parameter type for the function that keeps a reference to the object?
shared_ptr or unique_ptr, if you want it to take responsibility for the object's lifetime and not otherwise worry about it. A raw pointer or reference, if you can (simply and reliably) arrange for the object to outlive everything that uses it.
Most of the other answers cover this, but #T.C. linked to a few really good guidelines which I'd like to summarise here:
Factory function
A factory that produces a reference type should return a unique_ptr by default, or a shared_ptr if ownership is to be shared with the factory.
-- GotW #90
As others have pointed out, you as the recipient of the unique_ptr can convert it to a shared_ptr if you wish.
Function parameters
Don’t pass a smart pointer as a function parameter unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.
Prefer passing objects by value, *, or &, not by smart pointer.
-- GotW #91
This is because when you pass by smart pointer, you increment the reference counter at the start of the function, and decrement it at the end. These are atomic operations, which require synchronisation across multiple threads/processors, so in heavily multithreaded code the speed penalty can be quite high.
When you're in the function the object is not going to disappear because the caller still holds a reference to it (and can't do anything with the object until your function returns) so incrementing the reference count is pointless if you're not going to keep a copy of the object after the function returns.
For functions that don't take ownership of the object:
Use a * if you need to express null (no object), otherwise prefer to use a &; and if the object is input-only, write const widget* or const widget&.
-- GotW #91
This doesn't force your caller to use a particular smart pointer type - any smart pointer can be converted into a normal pointer or a reference. So if your function doesn't need to keep a copy of the object or take ownership of it, use a raw pointer. As above, the object won't disappear in the middle of your function because the caller is still holding on to it (except in special circumstances, which you would already be aware of if this is an issue for you.)
For functions that do take ownership of the object:
Express a “sink” function using a by-value unique_ptr parameter.
void f( unique_ptr<widget> );
-- GotW #91
This makes it clear the function takes ownership of the object, and it's possible to pass raw pointers to it that you might have from legacy code.
For functions that take shared ownership of the object:
Express that a function will store and share ownership of a heap object using a by-value shared_ptr parameter.
-- GotW #91
I think these guidelines are very useful. Read the pages the quotes came from for more background and in-depth explanation, it's worth it.
I would return a unique_ptr by value in most situations. Most resources shouldn't be shared, since that makes it hard to reason about their lifetimes. You can usually write your code in such a way to avoid shared ownership. In any case, you can make a shared_ptr from the unique_ptr, so it's not like you're limiting your options.

I have a reference and want to call a function that takes boost::shared_ptr

I have a reference to an object and want to call a function that takes a boost::shared_ptr of this object. If I build a boost::shared_ptr to make the call when my boost::shared_ptr is canceled from the stack than the object is canceled too! This is exactly what happens when I run this code:
double f(boost::shared_ptr<Obj>& object)
{
...
}
double g(Obj& object)
{
boost::shared_ptr<Obj> p(&object);
double x = f(p);
...
}
Is there a way to make it work? How can I create in g() a boost::shared pointer that leaves my object alive at the end? I think I have to connect it to the reference counting machinery of other shared pointers that already point to object... but how?
Even if I make it work do you think this way of doing is bad design? What is the best practice to solve this kind of problems? In my code I have objects and methods that work both with shared pointer and references and I cannot work only with these or those...
A function that takes a shared_ptr is saying something about what it does. It is saying, "I want to potentially claim shared ownership of this object". If this is not true, then it is a poorly written function and shouldn't be taking a shared_ptr at all.
A function which takes a value by non-const reference to an object means that the function can modify the object, but cannot claim ownership. If you don't own something, you also can't give ownership to someone else.
Now, you could perform this trick of using an empty deleter function:
void EmptyDeleter(Obj *) {}
double g(Obj& object)
{
boost::shared_ptr<Obj> p(&object, EmptyDeleter);
double x = f(p);
...
}
However, you are now lying to f. It doesn't own object; it can't own object. It is very possible that object is a stack object that may disappear any time after f completes. If f were a member of a class, it might store the shared_ptr in a member variable. At which point, it would then have a shared_ptr to a dead object. This is exactly the sort of thing that shared_ptrs are intended to prevent.
The correct answer is for either f to not take its argument by shared_ptr (use non-const reference or non-const pointer if it is modifiable, and const& if it is not modifiable), or for g to take its argument by shared_ptr.
You may create a shared_ptr that doesn't actually free the object. Like this:
struct FictiveDisposer {
template <class T> void operator ()(T) {}
};
Obj& object = /* ... */;
boost::shared_ptr<Obj> myPtr(&obj, FictiveDisposer ());
// you may use myPtr
However you should use this carefully. If you're sure the function you're calling won't try to "save" your object for later use - there's no problem. Otherwise you must guarantee that the lifetime of the saved shared_ptr to your object won't exceed the actual lifetime of your object.
In simple words: you got the reference to the object. You didn't create it, and you may not affect its lifetime (neither shared_ptr can). Hence there may happen a situation where the object doesn't exist anymore, still it's referenced by shared_ptr. This must be avoided.
You must consider the purpose of f(). Presumably if it takes a shared_ptr, f intends to retain shared ownership of this pointer over time, past its return. Why? What is f() assuming when you pass it a shared_ptr? Once you answer this question you will be able to figure out how to code g().
If for some reason f() does not need to retain shared ownership of the pointer, then if you have control over its interface it could be rewritten to take a Obj* or Obj& instead of a shared_ptr. Any code possessing a shared_ptr could then call f by pulling the pointer out of the shared_ptr or dereferencing it.
It's usually a sign of poor design for a library interface to take a
shared_ptr (but there are exceptions). Since the function you're
calling expects to take responsibility, or at least partial
responsibility, for the object you pass it, and the rest of the code
isn't prepared for this, you're only safe solution is to clone the
object, e.g.:
double x = f( boost::shared_ptr<Obj>( new Obj( object ) ) );
But you'd really be best off finding out why f requires a
shared_ptr, and why g can't take one as an argument.
How can I create in g() a boost::shared pointer that leaves my object alive at the end?
You can give the shared pointer a custom destructor that does nothing:
boost::shared_ptr<Obj> p(&object, [](void*){});
or if your compiler doesn't support lambdas:
void do_nothing(void*) {}
boost::shared_ptr<Obj> p(&object, do_nothing);
Even if I make it work do you think this way of doing is bad design?
Yes: you lose the lifetime management that shared pointers give you, and it is now your responsibility to make sure that the object outlives all of the shared pointers.
What is the best practice to solve this kind of problems?
Decide on an ownership model for all the objects you're using, and stick to it. Shared pointers can be useful when you want to share ownership, but not otherwise. In your case f wants to share ownership, and whatever calls g seems to want exclusive ownership; it would be a good idea to think about why they want that, and whether you can change one to be compatible with the other.
std::shared_ptr<T> is to possible give multiple entities ownership of the referenced object. If an interface expects a std::shared_ptr<T> there are two possibilities:
Someone ignorantly used std::shared_ptr<T> in an interface which was meant to receive a T object or a reference or a pointer to a T object. If that is the case the author shall be educated (and if this doesn't work be released from his current duties to pursue a new career) and the interface corrected.
Since now all interfaces using a std::shared_ptr<T> are using this to possibly grant shared ownership to the object, it should be obvious that a stack allocated T isn't a suitable argument to such an interface. The only possible argument is a T object whose life-time is maintained vy a std::shared_ptr<T>.
I realize that this doesn't answer the original question but it should be clear that the only viable course of action is: don't ever try to pass an object to a function taking a std::shared_ptr<T> which can't be fully controlled by such a pointer! (the same applies to the boost version of shared pointers).

questions regarding shared_from_this

I have a function which takes a shared_ptr<MyClass>.
In some member function memfun of MyClass, I need to pass this to that function. But if I write
void MyClass:memfun()
{
func(shared_ptr<MyClass>(this))
}
I am assuming that after the call has ended the reference count will reach 0 and this will be attempted to be destroyed, which is bad.
Then I remembered that there this class enable_shared_from_this with the function shared_from_this.
So now I am going to use the following:
class MyClass: public enable_shared_from_this<MyClass>
{
void MyClass:memfun()
{
func(shared_from_this());
}
};
Questions are:
1) Is is absolutely impossible to use the functionality without deriving from enable_shared_from_this?
2) Does deriving from enable_shared_from_this mean that calling memfun on an object with automatic storage duration will result in something bad? E.g.
int main()
{
MyClass m; //is this OK?
m.memfun(); // what about this?
}
3) If I derive from MyClass, will the enable_shared_from_this functionality be correctly inherited or do I need to derive again? That is,
class MyCoolClass: public Myclass
{
void someCoolMember
{
someCoolFuncTakingSharedPtrToMyCoolClass(shared_from_this());
}
}
Is this OK? Or correct is the following?
class MyCoolClass: public Myclass, public enable_shared_from_this<MyCoolClass>
{
void someCoolMember
{
someCoolFuncTakingSharedPtrToMyCoolClass(enable_shared_from_this<MyCoolClass>::shared_from_this());
}
}
Thanks very much in advance.
1) It depends on what you mean by "do this" as to whether or not you can. You can always construct a shared_ptr from a raw pointer such as this, but it won't share the reference count with another shared_ptr instance that was separately constructed from a raw pointer. You will thus need to use a custom deleter on one or other instance to avoid double deletions, but unless you take great care then you may end up with dangling shared_ptr instances due to the object being deleted through one, but still accessible from another.
shared_from_this enables you to guarantee that if you have one shared_ptr instance to your object then you can construct another without copying the first, and that these instances will share the reference count. You could achieve this by storing a weak_ptr as a class member, and setting that value when you first allocate a shared_ptr to your object.
2) Calling shared_from_this() requires that there is at least one shared_ptr instance already pointing to your object. If you use it on an automatic object without a shared_ptr instance with a custom deleter then you will get bad stuff happening.
3) If you derive from your class then the enable_shared_from_this functionality will give you a shared_ptr to the base class (the one that derived from enable_shared_from_this). You could then use static_pointer_cast or dynamic_pointer_cast to cast the result of shared_from_this() to a pointer to the derived class.
The important question here is why does the function take the argument through a shared_ptr. Does it store the pointer internally for later use? Does it only use it for the duration of the call? Why is the ownership diluted among the caller and the callee?
Some answers suggest that you provide a no-op deleter if you are going to pass a stack allocated object into the function, but if the function is actually storing the shared_ptr for later use, it might be the case that by the time it gets around to it, the locally allocated object is no longer in the stack and you trigger UB. Having the no-op deleter shared_ptr will allow the call, but the semantics will not be correct.
If the function does not store the shared_ptr for later use, what was the design decision that led to that API? If you can change the function (and there is no impending reason), make it receive the argument by reference and you will have a friendlier interface that does not impose a shared_ptr for no reason.
If at the end you determine that you can guarantee that the object in the stack will be alive for the whole duration of the process triggered by that function call, then and only then use the no-op deleter.
1) No, it's not impossible to do this without shared_from_this. You can simply construct a shared_ptr with a no-op deleter:
void do_nothing(MyClass*) {}
void MyClass:memfun()
{
func(shared_ptr<MyClass>(this, do_nothing));
}
Seeing as you don't actually seem to need shared_from_this after all, I'm going to skip the next two parts of your question.
If you have an object with automatic storage and a function that requires shared_ptr and you know that the lifetime of your object will be long enough for the duration of the function and that it does not store the shared_ptr anywhere, then you can pass it with a no-op deleter.
This is useful for static objects. If it really does have local automatic storage, you need to ask yourself why the function is taking shared_ptr. Does it store them?
There is another lesser-known constructor to shared_ptr for an object that is a member of another reference-counted object. You can actually create a shared_ptr with the shared_ptr from the outer object and the pointer from the inner object.
In addition with David Rodríguez - dribeas, shared pointer isn't recommended by google
It maintains reference count internally, so making it work correctly, InterlockedIncrement and InterlockedDecrement are used, these two functions are really slower than normal ++ and --.
You should check this object ownership truly need be shared with others, per my experience, shared pointer could be avoided in most cases.

boost shared_from_this<>()

could someone summarize in a few succinct words how the boost shared_from_this<>() smart pointer should be used, particularly from the perspective of registering handlers in the io_service using the bind function.
EDIT: Some of the responses have asked for more context. Basically, I'm looking for "gotchas", counter-intuitive behaviour people have observed using this mechanism.
The biggest "gotcha" I've run into is that it's illegal to call shared_from_this from the constructor. This follows directly from the rule that a shared_ptr to the object must exist before you can call shared_from_this.
From my understanding, sometimes in your code you want a class to offer up shared_ptr's to itself so that other parts of your code can obtain shared_ptr's to an object of your class after it has been constructed.
The problem is that if your class just has a shared_ptr<> to itself as a member variable, it will never get automatically destructed, since there is always "one last reference" hanging around to itself. Inheriting from enable_shared_from_this gives your class an automatic method which not only returns a shared_ptr, but only holds a weak shared pointer as a member variable so as not to affect the reference count. This way, your class will be freed as usual when the last reference to it is gone.
I've never used it, but this is my understanding of how it works.
shared_from_this<> is used if an object wants to get access to a shared_ptr<> pointing to itself.
Usually an object only knows about the implicit this pointer, but not about any shared_ptr<> managing it. Also, this cannot easily be converted into a shared_ptr<> that shares ownership with other existing shared_ptr<> instances, so there is no easy way for an object to get a valid shared_ptr<> to itself.
shared_from_this<> can be used to solve this problem. For example:
struct A : boost::enable_shared_from_this<A> {
server *io;
// ...
void register_self() {
io->add_client(shared_from_this());
}
};
the boost::asio::io_service destructor documentation explains it fairly well
The destruction sequence described
above permits programs to simplify
their resource management by using
shared_ptr<>. Where an object's
lifetime is tied to the lifetime of a
connection (or some other sequence of
asynchronous operations), a shared_ptr
to the object would be bound into the
handlers for all asynchronous
operations associated with it. This
works as follows:
When a single connection ends, all associated asynchronous operations
complete. The corresponding handler
objects are destroyed, and all
shared_ptr references to the objects
are destroyed.
To shut down the whole program, the io_service function stop() is called
to terminate any run() calls as soon
as possible. The io_service destructor
defined above destroys all handlers,
causing all shared_ptr references to
all connection objects to be
destroyed.
Typically your objects will chain asynchronous operations where the handlers are bound to member functions using boost::bind and boost::shared_from_this(). There are some examples that use this concept.
Stuff is missing from some of the comments above. Here's an example that helped me:
Boost enable_shared_from_this example
For me, I was struggling with errors about bad weak pointers. You HAVE to allocate your object in a shared_ptr fashion:
class SyncSocket: public boost::enable_shared_from_this<SyncSocket>
And allocate one like this:
boost::shared_ptr<SyncSocket> socket(new SyncSocket);
Then you can do things like:
socket->connect(...);
Lots of examples show you how to use shared_from_this() something like this:
boost::asio::async_read_until(socket, receiveBuffer, haveData,
boost::bind(&SyncSocket::dataReceived, shared_from_this(), boost::asio::placeholders::error));
But was missing for me was using a shared_ptr to allocate the object to begin with.