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.
Related
I am not deeply familiar with async programming and I have a question.
My question is the following. Given the echo_server example here for C++11 in boost.asio: http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp
I would like to know if the std::make_shared<session> can be replaced in C++14 with a std::unique_ptr<session>in C++14, avoiding the overhead of reference count.
I am not sure since we have shared_from_this() but not something like unique_from_this(), so how can I access the unique_ptr<session> from inside this?.
No, the use of shared_ptr in asio programming is idiomatic.
The idea is that the number of outstanding handlers is matched by the shared-count of the object initiating the async operations. This is achieved by binding a copy of the shared_ptr managing the object into the handler function objects.
The c++11/14 way would be to replace the boost::shared_ptr with std::shared_ptr (std::bind, lambdas, etc also work perfectly well with asio).
Update, now that I fully understand the question:
In the example you linked, I take it that you're referring to the shared_ptr called self which is created in the method go() ? You could write it without the shared_ptr if you wanted. You'd have to put a delete this as the last line of go(). You'd also have to remember to catch any exceptions to ensure this code path was taken. A unique_ptr could be set up to do this of course, but then you've got a lifetime management issue between the construction of the session and the successful creation of the adopting unique_ptr. shared_ptr eases the management burden for the cost of one atomic inc...
In which case the answer is strictly "yes", but imho I'll-advised as it's more brittle.
As I understand it, your session object will go through a pipeline of handlers, one at a time. The state of your session is never shared. Why a unique_ptr would not make sense? The point is that when the latest handler is finished, the memory will be released. Does this hold true?
Yes, this is the trick. The library has been designed around copyable completion handlers.
If you worry about overhead, indeed avoid shared_ptr.
In that case, just carry a reference to some state with externally controlled lifetime. Just make sure it stays alive (just as you do with the io_service object itself).
I read about std::enable_shared_from_this and I understand how it works, but I don't understand what problem it designed to solve?
For example from here: What is the usefulness of `enable_shared_from_this`?
class Y: public std::enable_shared_from_this<Y>
{
public:
std::shared_ptr<Y> f()
{
return shared_from_this();
}
};
std::shared_ptr<Y> p(new Y);
std::shared_ptr<Y> q = p->f();
yeah, great we can write q=p->f();, but why not just
q = p;?
In general case we have shared_ptr, but for some reason it is not available somewhere, so we have to restore it from this, but if we pass raw pointer from shared_ptr to somewhere then we have problem, because of all shared_ptr safety go away if we take pointer from std::shared_ptr::get,
and pass raw pointer to someone.
You have a method in your class that needs to hand out weak or shared pointers to this. Not just return, but maybe call a different function, passing a shared_ptr pointing to itself to it.
You either have to augment the method with a shared-ptr-to-this, change it to a non-method taking a shared ptr, store a weak ptr to this in the class, or inherit from enable_shared_from_this.
enable_shared_from_this is basically "store a weak_ptr to yourself", with some help from the shared-ptr creating code to initialize it.
Y::f() may want to call another function which takes shared_ptr<Y> or shared_ptr to some other type which happens to be a sub-object or member of Y.
I think it I found a more satisfactory real-life example.
In Boos.Asio you can program asynchronously. When you call an async function, it returns immediately. Though you want to keep certain resources alive but these go out of scope. How can you achieve asynchronous programming in a nice way?
Well, a pattern is thinking of a pipeline, where, for example, you want to listen to connections and later perform some operation. Look at the class tcp_connection here: https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html
So, what does this server do? It creates a tcp connection that waits for a request and returns the daytime.
As you can see the connection holds the socket and a string (resources to be kept alive). So async_read and async_write will be called on it. In order to keep the tcp_connection instance alive, shared_from_this() is passed to each handler in the pipeline, binding lifetime of tcp_connection to that of the handlers: the state will be kept alive exactly for as long as needed. If there is another phase in the pipeline it is a matter of forwarding the reference count to the next pipeline phase. keeping the tcp_connection alive this way makes sure it will not last longer or shorter than it should: it will last exactly what it needs to assist the request and return.
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.
Is anyone aware of an implementation of shared_ptr and weak_ptr together with a lazy initialization partner? The requirements of the classes were:
A lazy_ptr class that allows a client to construct the object later (if at all), without needing the constructor implementation
A weak_lazy_ptr class that has three possible states: not yet constructed (won't lock to a shared_ptr), constructed (will lock to a shared_ptr) and destroyed (won't lock to a shared_ptr)
I created some classes that didn't do the job completely a while ago (see CVu article here) that used shared_ptr and weak_ptr in their implementation. The main problems with a model that USES shared and weak pointers instead of integrating with them follow:
Once all lazy_ptr objects go out of scope, any weak references can no longer be locked, even if other clients are holding shared_ptr versions
Construction of objects on different threads can't be controlled
I'd appreciate any pointers to other attempts to reconcile these problems, or to any work in progress there may be in this area.
To create deferred construction that requires no parameters:
boost::bind( boost::factory<T*>(), param1, param2 ) will create a function object that performs the equivalent of new T(param1, param2) without needing the parameters at the time of construction.
To create a shared_ptr that supports this deferred construction:
Bundle your factory with the standard boost::shared_ptr (in a class of your creation, for example), and you'llget the results you describe, including the appropriate weak_ptr functionality...
Whatever code triggers the deferred construction by the client should run:
your_shared_ptr.reset( your_factory() );
Whatever code triggers the object's destruction should run:
your_shared_ptr.reset();
The shared pointer will evauluate to true only during the object's lifetime. And if you want you differentiate "not yet constructed" from "destroyed", you can set a bool after the factory is run.
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.