C++ asynchronous call best practice - c++

I'm working with boost::asio. I wrote a class responsible for asynchronous reading from socket.
In my application io_service can be stopped and started many times during one application run.
So I have to worry about memory leakage when service is stopped.
I came to two solutions:
A class asking for asynchronous request provides function with a buffer for using in asio reads, and it is responsible for its freeing. This is an obvious solution but I don't like it. Passing a parameter you don't need to a function looks realy strange.
Smart pointer binded to a callback. Example here:
http://pastebin.com/p8nQ5NFi
Now I'm using the second solution but however I'm feeling, I'm inventing a wheel. What's a common practice for buffer cleanage in asynchronous call? Are there any hidden problems in my aproach?

The shared_ptr approach is fairly common. However, instead of passing a shared_ptr as an additional argument to bind, it is possible to pass the shared_ptr as the instance object in place of this.
boost::shared_ptr< my_class > ptr( this );
boost::asio::async_read( stream, buffer,
boost::bind( &my_class::read_handler, ptr,
boost::asio::placeholders::error
boost::asio::placeholders::bytes_transferred ) );
Often, since the instance is going to be managed via a shared_ptr, which may or may not be in the context of this, it is a good idea to use Boost.SmartPointer's enable_shared_from_this. When a class inherits from boost::enable_shared_from_this, it provides a shared_from_this() member function that returns a valid shared_ptr instance to this.
class my_class: public boost::enable_shared_from_this< my_class >
{
void read()
{
boost::asio::async_read( stream, buffer,
boost::bind( &my_class::read_handler, shared_from_this(),
boost::asio::placeholders::error
boost::asio::placeholders::bytes_transferred ) );
}
};
boost::shared_ptr< my_class > foo( new my_class() );
foo->read();
In this snippet, foo.get() and foo->shared_from_this() both point to the same instance. This helps prevent difficult to locate memory leaks. For example, in the original example code, a memory leak occurs in Protocol::AsyncReadMessage if AsyncReadHandler's copy-constructor throws when trying to invoke AsyncReadMessage. Boost.Asio's asynchronous TCP daytime server and many of the examples show enable_shared_from_this being used within Boost.Asio. For a deeper understanding, this question specifically covers asynchronous Boost.Asio functions and shared_ptr.
Also, in the original code, it may be easier to make Protocol::AsyncHelper a template class instead of having it be a non-templated class with template member functions. This would allow the AsyncHelper to accept the protocol, stream, and handler as constructor arguments, storing them as member variables. Additionally, it makes the bind calls slightly easier to read since it reduces the amount of arguments needing to be passed and since the member functions are no longer templates, there is no need to specify their full type. Here is a quick pass at an example.

Related

C++ shared_ptr shared_from_this throws a bad_weak_ptr exception, even though I have a reference to it

EDIT: I never figured this out - I refactored the code to be pretty much identical to a Boost sample, and still had the problem. If anyone else has this problem, yours may be the more common shared_from_this() being called when no shared_ptr exists (or in the constructor). Otherwise, I recommend just rebuilding from the boost asio samples.
I'm trying to do something that I think is pretty common, but I am having some issues.
I'm using boost asio, and trying to create a TCP server. I accept connections with async_accept, and I create shared pointers. I have a long lived object (like a connection manager), that inserts the shared_ptr into a set. Here is a snippet:
std::shared_ptr<WebsocketClient> ptr = std::make_shared<WebsocketClient>(std::move(s));
directory.addPending(ptr);
ptr->onConnect(std::bind(&Directory::addClient, &directory, std::placeholders::_1));
ptr->onDisconnect(std::bind(&Directory::removeClient, &directory, std::placeholders::_1));
ptr->onMessage(std::bind(&Directory::onMessage, &directory, std::placeholders::_1, std::placeholders::_2));
ptr->start();
The Directory has std::set<std::shared_ptr<WebsocketClient>> pendingClients;
The function for adding a client is:
void Directory::addPending(std::shared_ptr<WebsocketClient> ptr){
std::cout << "Added pending client: " << ptr->getName() << std::endl;
pendingClients.insert(ptr);
}
Now, when the WebsocketClient starts, it tries to create a shared_ptr using shared_from_this() and then initiates an async_read_until ("\r\n\r\n"), and passes that shared_ptr to the lambda to keep ownership. It crashes before actually invoking the asio function, on shared_from_this().
Call stack looks like this:
server.exe!WebsocketClient::start()
server.exe!Server::acceptConnection::__l2::<lambda>(boost::system::error_code ec)
server.exe!boost::asio::asio_handler_invoke<boost::asio::detail::binder1<void <lambda>(boost::system::error_code),boost::system::error_code> >(boost::asio::detail::binder1<void <lambda>(boost::system::error_code),boost::system::error_code> & function, ...)
server.exe!boost::asio::detail::win_iocp_socket_accept_op<boost::asio::basic_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::ip::tcp,void <lambda>(boost::system::error_code) ::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned __int64 __formal) Line 142 C++
server.exe!boost::asio::detail::win_iocp_io_service::do_one(bool ec, boost::system::error_code &)
server.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec)
server.exe!Server::run()
server.exe!main(int argc, char * * argv)
However, I get a bad_weak_ptr when I call shared_from_this. I thought that was thrown when no shared_ptr owned this object, but when I call the addPending, I insert "ptr" into a set, so there should still be a reference to it.
Any ideas? If you need more details please ask, and I'll provide them. This is my first post on StackOverflow, so let me know what I can improve.
You could be dealing with memory corruption. Whether that's the case or not, there are some troubleshooting steps you should definitely take:
Log the pointer value returned from make_shared, and again inside the member function just before calling shared_from_this. Check whether that pointer value exists in your running object table (which is effectively what that set<shared_ptr<...>> is)
Instrument constructor and destructor. If the shared_ptr count does actually hit zero, it'll call your destructor and the call stack will give you information on the problem.
If that doesn't help, the fact that you're using make_shared should be useful, because it guarantees that the metadata block is right next to the object.
Use memcpy to dump the raw bytes preceding your object at various times and watch for potential corruption.
Much of this logging will happen in a context that's exhibiting undefined behavior. If the compiler figures out that you're testing for something that's not supposed to be possible, it might actually remove the test. In that case, you can usually manage to make the tests work anyway by precision use of #pragma to disable optimization just on your debug logging code -- you don't want to change optimization settings on the rest of the code, because that might change the way corruption manifests without actually fixing it.
It is difficult to determine the cause of the problem without a code.
But which enable_shared_from_this you use, boost or std?
I see you use std::make_shared, so if WebsocketClient inherits boost::enable_shared_from_this it can cause crash.

Can i have boost asio socket references in two different class instances?

I want to std::move(my_asio_socket) to the instance of some class. What if I do the same for an instance of some other class?
My purpose is to read_async in one class instance (let's say class A), and to execute write_async in the other (let's say class B). Because of some functionality implementations, I should do it this way.
Any suggestion would be nice.
UPDATED
it's not working properly as i expected.
The VS2015(vc14 compiler) shows me a kind of exception while debugging:
Microsoft C++ exception: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> > at memory location 0x02D8E3BC.
And after i hit continue in VS it show me that:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
As i said, i'm trying to boost::move (or std::move) the socket to other class instance. Here is a snippet of code of what i'm doing:
boost::shared_ptr<connection> new_connection_;//it's a field in my class,
//that's why i should reset it later
new_connection_.reset(new connection(std::move(socket_), io_service_));
new_connection_->start();
Now here is my connection ctor:
connection::connection(boost::asio::ip::tcp::socket sock, boost::asio::io_service& io_ptr)
: socket_(boost::move(sock)),
io_ptr_(io_ptr),
remote_ep(socket_.remote_endpoint()),
//request_handler_(new request_handler(boost::move(socket_))),
work(new boost::asio::io_service::work(io_ptr))
{
boost::shared_ptr<request_handler> req_ptr(new request_handler(boost::move(socket_)));
request_handler_.swap(req_ptr);
}
As you can see, i've tried initializing in the commented line, but it shows me the same result.
Here is the ctor for request_handler:
request_handler::request_handler(boost::asio::ip::tcp::socket sock):
socket_(boost::move(sock)){ }
And here is my method connection::start where the problem detects:
void connection::start()
{
boost::asio::ip::tcp::socket::keep_alive kl(true);
boost::asio::ip::tcp::socket::enable_connection_aborted eca(true);
// here it breaks, when trying to set an option
socket_.set_option(eca);
socket_.set_option(kl);
socket_.async_read_some(boost::asio::buffer(buffer_),
boost::bind(&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
This problem appears only when i use to move socket into the new instance of request_handler. If i'm not - then all goes okey. I can't understand what reason it could be, but seems like my socket_ (i declare it everywhere without any & or *) field from connection class is lost or kind of. But the debugger isn't showing me smthing like null, so i don't know what is it.
In general it is not guaranteed:
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. However, this behaviour should not be relied upon.
But according to the documentation for tcp::socket it is left in the same state:
Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_service&) constructor.

Async I/O operations - proper way to avoid deleting object

Using async I/O operations from boost::asio I often need shared pointers (and enable_shared_from_this and shared_from_this in callbacks) to avoid deleting objects too early.
I think that it could be done by keeping unique_ptr or just object (ownership) in class (as a member)
For example:
Only foo method use sender.
1st (popular solution):
class C {
public:
void foo
{
std::shared_ptr<Sender> sender = std::make_shared<Sender>();
sender->send();
// class Sender use async_write
// inheritance: enable_shared_from_this
// callback in async operation created with argument shared_from_this
}
};
Why nobody(?) use this solution:
class D {
public:
void foo
{
sender.reset(new Sender);
sender->send();
}
private:
std::unique_ptr<Sender> sender;
};
I know that sender will not be deleted to early. I have no shared_ptrs. I think it's good to avoid them because if callback in Sender class also use async operations I need another shared pointers etc. I think that class D is more friendly to read.
But I wonder if it's a good style... and I always see solution with shared_ptrs in the net.
You can only have one unique_ptr to an object. What happens if you have both a send and a receive operation pending? What happens if you have both a receive operation and a timer?
Yes, you could use a unique_ptr, but then you'd have to implement your own count of the number of outstanding operations. You'd have to increment and decrement that count in a thread-safe way. And you'd have to constantly check if that count was zero to invoke the destructor. To clean this up, you'd likely bundle all this functionality into its own class. And you'd have reinvented shared_ptr.
The latter usage is fragile and makes no guarantee that the sender will not be deleted too early. For instance, consider the case where D::foo() is called consecutively, before the asynchronous operations have completed. The previous Sender object could be deleted with outstanding operations that may depend on the Sender object:
public: Sender
{
public:
void send()
{
boost::asio::async_write(socket_, boost::asio::buffer(buffer_), ...);
}
private:
std::array<char, 64> buffer_;
boost::asio::ip::tcp::socket socket_;
...
};
D d;
d.foo(); // Create Sender1, initiate async_write.
d.foo(); // Delete Sender1, create Sender2, initiate async_write.
io_service.run(); // Sender1's async_write invokes undefined behavior.
In the above code, the second call to d.foo() will delete the first Sender object that has outstanding operations, resulting in undefined behavior. On the other hand, if Sender inherits from enable_shared_from_this, and the result of shared_from_this() is bound to the handlers for asynchronous operations, then the Sender object's lifetime would extend to be at least as long as the operations.
Have you looked at asio::spawn? Basically, it takes most of the complexity out of async C++ programming, and allow you to just put your objects on the stack.
Here is a simple example: modern.cpp
Using this approach saves a lot of time implementing and debugging an async application, and it makes the code really easy to understand. (I once implemented a RTP over TCP proxy, using traditional callbacks. It turned out to be a nightmare to maintain later on).
Regarding shard versus unique pointers - my experience is that shared pointers are simpler to use with asio. There were some problems moving unique pointers around, and when the program becomes slightly complex, it's really easy to make mistake mistakes. I think I would stick with shared and weak pointers as default - and only switch to unique pointers for objects where the profiler outputs suggests that it's worth the while.

Pattern for safe asynchronous callbacks in C++

What alternatives does one have to the following code for performing safe asynchronous callbacks on an object?
class MyClass : public std::enable_shared_from_this<MyClass>
{
private:
void fetchResults()
{
std::weak_ptr<MyClass> weakSelf = shared_from_this();
m_service.getResultAsync(
/* args... */,
/* Callback */
[weakSelf](Result r)
{
auto self = weakSelf.lock();
if (self)
{
self->workFinishedWithResult(std::move(r));
}
});
}
void workFinishedWithResult(Result r) { // ... continue workflow }
std::shared_ptr<Service> m_service;
};
I would like to avoid using enable_shared_from_this (and avoid clients of m_service requiring it for what is a very common use case), but it seems difficult to extend the lifetime of MyClass once inside the callback without it.
Capturing this in the lambda instead and trying to deregister it in MyClass' destructor, or preventing MyClass from being destructed until the callback is finished is a path that leads to races, deadlocks and a loss of simplicity. I'm almost certain that capturing 'this' can't be made safe.
It seems if MyClass is asking a shared_ptr<Service> to call it back, it can only guarantee that it remains valid if it can manage or extend its own lifetime (via enable_shared_from_this) since it doesn't know how long the callback will live for. Otherwise it would have to be the responsibility of whoever owns MyClass, or whoever knows the lifetime of both the Service and MyClass to deal with this, but it all becomes very error-prone and impractical.
It seems the only viable solutions are:
Use enable_shared_from_this with the "capture weakly" pattern (as in the above code)
Have MyClass be given a Service& so it is the caller's responsibility to ensure the service outlives it.
Use a static method/function as the callback and pass everything it needs in by-value (problem is that sometimes you really do want to pass control back into MyClass and you have the same problem).
What are the alternatives here? Or does using enable_shared_from_this just become inevitable when doing async C++?
The exact thing that you're looking for would be std::future<T>::then(). It does not exist in C++11, but boost::future offers it.
However, in the general case, it would be the responsibility of the caller to ensure that the service and MyClass instances live long enough, although it would be also acceptable if the method takes an owning reference to the service.

Memory management in asynchronous C++ code

I have been working with boost::asio for a while now and while I do understand the concept of the asynchronous calls I am still somewhat befuddled by the memory management implications. In normal synchrous code the object lifetime is clear. But consider a scenario similar to the case of the daytime server:
There might be multiple active connections which have been accepted. Each connection now sends and receives some data from a socket, does some work internally and then decides to close the connection. It is safe to assume that the data related to the connection needs to stay accessible during the processing but the memory can be freed as soon as the connection is closed. But how can I implement the creation/destruction of the data correctly? Assuming that I use classes and bind the callback to member functions, should I create a class using new and call delete this; as soon as the processing is done or is there a better way?
But how can I implement the creation/destruction of the data correctly?
Use shared_ptr.
Assuming that I use classes and bind the callback to member functions, should I create a class using new and call delete this; as soon as the processing is done or is there a better way?
Make your class inherit from enable_shared_from_this, create instances of your classes using make_shared, and when you bind your callbacks bind them to shared_from_this() instead of this. The destruction of your instances will be done automatically when they have gone out of the last scope where they are needed.