boost shared_from_this<>()
Asked Answered
B

5

16

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.

Blum answered 2/9, 2010 at 17:23 Comment(2)
What exactly don't you understand? It's hard to answer an undirected question.Johan
The only way I could attempt to illustrate an example was by pasting in reams of code, which, being boost code, is dense enough as it is.Blum
S
35

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.

Selfappointed answered 2/9, 2010 at 21:8 Comment(2)
+1 good advice, typically I make my constructor provide and provide a static shared_ptr<Type> create method.Rate
I think you meant you make your constructor private.Lh
R
14

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.

Resinate answered 2/9, 2010 at 17:45 Comment(0)
H
11

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());
   }
};
Heptameter answered 2/9, 2010 at 18:1 Comment(0)
R
7

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.

Rate answered 2/9, 2010 at 18:53 Comment(1)
You're answer finally explained asio examples to me... Particularly what happens if there is an error in the connection and the http server example from asio.Beefeater
C
2

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.

Clymer answered 13/8, 2019 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.