Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way of ensuring valid object lifespan when using Boost.Asio?

Been playing a lot with Boost.Asio of late. I like the library a lot since it offers a fantastic way to squeeze performance out of today's multicore systems.

A question I have asked myself a few times, and I thought worth throwing out there regards object lifespan / ownership when making async calls with Asio.

The problem I've come accross repeatedly is that you quite often have to "expire" an object that still has async callbacks pending against it. If that object goes out of scope before the callback is invoked things inevitably go bang.

To combat this I've taken to using the boost::enable_shared_from_this template as a base class for most asio based classes. This works OK but it's a little burdensome: usually this also means protecting the constructor and adding a factory method to the class to ensure that all instances are created inside a shared_ptr.

I just wanted to know how other people had tackled this problem. Am I going about this the best way? Or have I got my Asio.Foo all wrong?

Discuss... :)

like image 494
jkp Avatar asked Jan 08 '09 09:01

jkp


People also ask

How does boost ASIO work?

At its core, Boost Asio provides a task execution framework that you can use to perform operations of any kind. You create your tasks as function objects and post them to a task queue maintained by Boost Asio. You enlist one or more threads to pick these tasks (function objects) and invoke them.

Is boost ASIO thread safe?

Thread Safety Like a regular Boost. Asio socket, a stream is not thread safe. Callers are responsible for synchronizing operations on the socket using an implicit or explicit strand, as per the Asio documentation.

Who uses Boost ASIO?

The systems software for managing an IBM Blue Gene/Q supercomputer uses Boost. Asio extensively. The source code is available under the Eclipse Public License (EPL) if you're interested.


1 Answers

Using boost::enable_shared_from_this is pretty much the way to do it. Additionally, look at using boost::weak_ptr if you need references to the object that should not preserve the object if they are the only references which remain.

A good example of using weak_ptr: I use enable_shared_from_this in my socket class which utilizes boost::asio. The boost::asio framework is the only thing that stores persistent references to the object, via read and write handlers. Thus, when the socket's destructor is called, I know that the socket is closed and I can "do stuff" in a handler to clean up for that closed socket. The application which uses the socket only has a weak_ptr reference to it, which it promotes to a shared_ptr when it wants to work with the socket (usually to write to it). That promotion can be checked for failure in case the socket went away, although the socket's close handler usually cleans up all the weak_ptr references appropriately before that even happens.

like image 176
user121826 Avatar answered Sep 30 '22 12:09

user121826