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.
Related
My API computes some data in its own thread:
/*** API is running in its own thread ***/
class API {
public:
std::shared_ptr<Data> retrieveData() { return mData; }
private:
std::shared_ptr<Data> mData;
std::mutex mDataMutex;
void run () {
std::thread t([](){
while (!exitApi) {
mDataMutex.lock();
updateData(mData);
mDataMutex.unlock();
});
t.join();
}
};
An application that uses my API will retrieve the shared data in another thread:
/*** Application is running in another thread ***/
class Application {
private:
Api mApi;
void run () {
std::thread t([](){
while (!exitApp) {
std::shared_ptr<Data> data = mApi.retrieveData();
/* API thread can update the data while the App is using it! */
useData(data);
});
t.join();
}
How can I design my API so that there are no pitfalls for the application-developer when retrieving the data? I can think of three options but do not like any of them:
Instead of sharing the pointer, the API will return a copy of all the data. However, the amount of data can get quite large and copying it should be avoided.
The API will lock the data when it hands it over to the application and the application needs to explicitly ask the API to unlock it again after performing all computations. Even if documented correctly this is very much prone to deadlocks.
When the API hands over the data to the application retrieveData will also return an already locked std::unique_lock. Once the application is done with using the data it has to unlock the unique_lock. This is potentially less prone to error but still not very obvious for the application developer.
Are there any better options to design the API (in modern C++11 and beyond) that is as developer-friendly as possible?
TL;DR: Use shared_ptr with a custom deleter that calls unlock.
It think the two main approaches are:
Returning an immutable data structure so it can be shared between threads. This is makes for a clean API, but (as already mentioned) copying could be expensive. Some approaches to reduce the need for copying would be:
Use a copy-on-write data structure so that only some portions of the data need to be copied each time. Depending on your data this may be not be
possible, or it will be too much work to refactor.
Make use of move-references where possible to reduce the cost of copying. This alone probably won't be enough, but depends on your actual data.
Using locks around a mutable data structure. As is pointed out, this requires the API user to perform extra actions that may not be obvious. But smart pointers can be used to lessen the burden on the consumers:
One way to make it easier is to return a custom smart pointer that
unlocks in its destructor: Unlock happens when the caller's scope closes, so there are no unlock calls for the caller to worry about. The API consumer would pass the pointer by reference to its methods. For example func(locking_ptr& ptr). A simple implementation can be found here: https://stackoverflow.com/a/15876719/1617480.
To be able to pass that locking smart pointer by copy instead of by reference, some sort of reference counting scheme needs to be in place. You'd probably want to use shared_ptr internal to the locking smart pointer to avoid rolling your own thread-safe reference counting. More simply pass a custom deleter to shared_ptr that unlocks and deletes (No need to write a smart pointer at all).
Another type of smart pointer would surround every dereference -> in locks. I don't think this is appropriate for this use case, since it looks the API consumer wants a consistent view of the results. Here's an example of such a pointer: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer
Another approach would involve closures, for example adding
// inside class API
void do_locked(std::function<void(Data*)>fun) {
std::guard_lock<std::mutex> gu(mDataMutex);
fun(mData);
}
and you could invoke it with a lambda expression
//inside Application::run2
mApi.do_locked([=](Data *dat) { useData(dat); });
I'm working with code, which has a lot of observer pattern implementations. All of them are organized in such a manner:
Some interface to be implemented by observers:
class ObserverInterface {
virtual void FooOccurs() = 0;
};
Some class, which implements Register, Unregister and notifications:
class ObservableImpl {
public:
Register(ObserverInterface *observer);
Unregister(ObserverInterface *observer);
private:
void SomeMethod() {
// foo things
for(auto &observer: observers) {
observer.FooOccurs();
}
}
};
Every time there is a copy-paste of Register and Unregister as well as implementation of notification for each method of ObserverInterface. And every time a programmer has to remember about calling Unregister(), if its observer is going to be destructed.
I wish to enclose the observer pattern in two class templates. So far I've got something like that:
http://rextester.com/UZGG86035
But I'm not sure if I'm not reinventing the wheel. Are there any easier, commonly known approach to do that?
In C++11, I'd advise a token-based approach.
You register an observer. An observer is just a std::function<void(Signature...)>.
The registration function return a token, a std::shared_ptr<void>. So long as that returned shared_ptr is valid, the broadcaster will continue to broadcast to that listener.
The listener is now responsible for maintaining that std::shared_ptr lifetime.
Inside the broadcaster, you hold a weak_ptr and .lock() it before broadcasting. If I don't really need to unregister (usually I do not), I lazily clean up my list of weak_ptrs. Otherwise, I the shared_ptr I return has a deletion function that does the unregistration.
Alternatively, your listeners are shared_ptr<std::function<void(Args...)>>, and internally you store weak_ptr to same.
In this model, you cannot inject an unregistraiton function easily. However, it does mean they can use the aliasing constructor themselves to tightly bind the lifetime of the callback to themselves, assuming they are managed by a shared_ptr.
In my experience, simply having listeners maintain a std::vector<token> is sufficient. If they have a more complex listening relationship they can do more work, maintaining keys and the like.
Hybrid models are also possible.
Both of these are acceptable for not-thread-safe broadcasting, and can be written in a few dozen lines of code.
Thread-safe broadcasting gets tricky. Often I find you are better off using a message-passing pattern for this rather than the alternatives, as this reduces the difficulty in reasoning about concurrency slightly.
This also doesn't deal with situations where you want to register listeners willy-nilly, and broadcaster and listener lifetime is like popcorn.
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.
Using boost::asio i use async_accept to accept connections. This works good, but there is one issue and i need a suggestion how to deal with it. Using typical async_accept:
Listener::Listener(int port)
: acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), port))
, socket(io) {
start_accept();
}
void Listener::start_accept() {
Request *r = new Request(io);
acceptor.async_accept(r->socket(),
boost::bind(&Listener::handle_accept, this, r, placeholders::error));
}
Works fine but there is a issue: Request object is created with plain new so it can memory "leak". Not really a leak, it leaks only at program stop, but i want to make valgrind happy.
Sure there is an option: i can replace it with shared_ptr, and pass it to every event handler. This will work until program stop, when asio io_service is stopping, all objects will be destroyed and Request will be free'd. But this way i always must have an active asio event for Request, or it will be destroyed! I think its direct way to crash so i dont like this variant, too.
UPD Third variant: Listener holds list of shared_ptr to active connections. Looks great and i prefer to use this unless some better way will be found. The drawback is: since this schema allows to do "garbage collection" on idle connects, its not safe: removing connection pointer from Listener will immediately destroy it, what can lead to segfault when some of connection's handler is active in other thread. Using mutex cant fix this cus in this case we must lock nearly anything.
Is there a way to make acceptor work with connection management some beautiful and safe way? I will be glad to hear any suggestions.
The typical recipe for avoiding memory leaks when using this library is using a shared_ptr, the io_service documentation specifically mentions this
Remarks
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.
For your scenario, change your Listener::handle_accept() method to take a boost::shared_ptr<Request> parameter. Your second concern
removing connection pointer from Listener will immediately destroy it,
what can lead to segfault when some of connection's handler is active
in other thread. Using mutex cant fix this cus in this case we must
lock nearly anything.
is mitigated by inheriting from the boost::enable_shared_from_this template in your classes:
class Listener : public boost::enable_shared_from_this<Listener>
{
...
};
then when you dispatch handlers, use shared_from_this() instead of this when binding to member functions of Listener.
If anyone interested, i found another way. Listener holds list of shared_ptr to active connections. Connections ending/terminating is made via io_service::post which call Listener::FinishConnection wrapped with asio::strand. Usually i always wrap Request's methods with strand - its safer in terms of DDOS and/or thread safety. So, calling FinishConnection from post using strand protects from segfault in other thread
Not sure whether this is directly related to your issue, but I was also having similar memory leaks by using the Boost Asio libraries, in particular the same acceptor object you mentioned. Turned out that I was not shutting down the service correctly; some connections would stay opened and their corresponding objects would not be freed from memory. Calling the following got rid of the leaks reported by Valgrind:
acceptor.close();
Hope this can be useful for someone!
I have found that boost::signals2 uses sort of a lazy deletion of connected slots, which makes it difficult to use connections as something that manages lifetimes of objects. I am looking for a way to force slots to be deleted directly when disconnected. Any ideas on how to work around the problem by designing my code differently are also appreciated!
This is my scenario: I have a Command class responsible for doing something that takes time asynchronously, looking something like this (simplified):
class ActualWorker {
public:
boost::signals2<void ()> OnWorkComplete;
};
class Command : boost::enable_shared_from_this<Command> {
public:
...
void Execute() {
m_WorkerConnection = m_MyWorker.OnWorkDone.connect(boost::bind(&Command::Handle_OnWorkComplete, shared_from_this());
// launch asynchronous work here and return
}
boost::signals2<void ()> OnComplete;
private:
void Handle_OnWorkComplete() {
// get a shared_ptr to ourselves to make sure that we live through
// this function but don't keep ourselves alive if an exception occurs.
shared_ptr<Command> me = shared_from_this();
// Disconnect from the signal, ideally deleting the slot object
m_WorkerConnection.disconnect();
OnComplete();
// the shared_ptr now goes out of scope, ideally deleting this
}
ActualWorker m_MyWorker;
boost::signals2::connection m_WorkerConnection;
};
The class is invoked about like this:
...
boost::shared_ptr<Command> cmd(new Command);
cmd->OnComplete.connect( foo );
cmd->Execute();
// now go do something else, forget all about the cmd variable etcetera.
the Command class keeps itself alive by getting a shared_ptr to itself which is bound to the ActualWorker signal using boost::bind.
When the worker completes, the handler in Command is invoked. Now, since I would like the Command object to be destroyed, I disconnect from the signal as can be seen in the code above. The problem is that the actual slot object is not deleted when disconnected, it is only marked as invalid and then deleted at a later time. This in turn appears to depend on the signal to fire again, which it doesn't do in my case, leading to the slot never expiring. The boost::bind object thus never goes out of scope, holding a shared_ptr to my object that will never get deleted.
I can work around this by binding using the this pointer instead of a shared_ptr and then keeping my object alive using a member shared_ptr which I then release in the handler function, but it kind of makes the design feel a bit overcomplicated. Is there a way to force signals2 to delete the slot when disconnecting? Or is there something else I could do to simplify the design?
Any comments are appreciated!
boost::signals2 does clean up the slots during connect/invoke.
So if all the slots disconnect themselves from the signal, invoking the signal a second time will not call anything but it should clean up the slots.
To answer your comment, yes, invoking the signal again is not safe if there are be other slots connected, as they will be invoked again. In that case I suggest you go the other way around and connect a dummy slot, then disconnect it when your "real" slot is invoked. Connecting another slot will clean up stale connections, so your slot should be released.
Just make sure that you don't keep any references that need freeing in the dummy slot, or you're back where you started.
This is an incredibly annoying aspect of boost::signals2.
The approach I took to resolve it is to store the signal in a scoped_ptr, and when I want to force disconnection of all slots, I delete the signal. This only works in cases when you want to forcefully disconnect all connections to a signal.
Is the behaviour any more strict with a scoped_connection?
So, rather than:
void Execute() {
m_WorkerConnection = m_MyWorker.OnWorkDone.connect(boost::bind
(&Command::Handle_OnWorkComplete, shared_from_this());
// launch asynchronous work here and return
}
...
boost::signals2::connection m_WorkerConnection;
Instead using:
void Execute() {
boost::signals2::scoped_connection m_WorkerConnection
(m_MyWorker.OnWorkDone.connect(boost::bind
(&Command::Handle_OnWorkComplete, shared_from_this()));
// launch asynchronous work here and return
} // connection falls out of scope
(copy-constructed from a boost::signals2::connection)
I've not used any sort of signalling so it's more of a guess than anything else, but following Execute() you wouldn't need to disconnect(), since scoped_connection handles it for you. That's more of a 'simplify the design' rather than actually solving your problem. But it may mean that you can Execute() and then immediately ~Command() (or delete the shared_ptr).
Hope that helps.
EDIT: And by Execute() then immediately ~Command() I obviously mean from outside your Command object. When you construct the Command to execute it, you should then be able to say:
cmd->Execute();
delete cmd;
Or similar.
I ended up doing my own (subset) implementation of a signal, the main requirement being that a slot should be destroyed by a call to connection::disconnect().
The implementation goes along the lines of the signal storing all slots in a map from slot implementation pointer to a shared_ptr for a slot implementation instead of a list/vector, thereby giving quick access to individual slots without having to iterate over all slots. A slot implementation is in my case basically a boost::function.
Connections have a weak_ptr to the internal implementation class for the signal and a weak_ptr to the slot implementation type to allow the signal to go out of scope and to use the slot pointer as the key into the signal map as well as an indication on whether the connection is still active (can't use a raw pointer as that could potentially be reused).
When disconnect is called, both of these weak pointers are converted to shared_ptrs and if both of these succeed, the signal implementation is asked to disconnect the slot given by the pointer. This is done by simple erasing it from the map.
The map is protected by a mutex to allow for multithreaded use. To prevent deadlocks, the mutex is not held while calling the slots, however this means that a slot may be disconnected from a different thread just prior to being called by the signal. This is also the case with regular boost::signals2 and in both of these scenarios one needs to be able to handle a callback from a signal even after one has disconnected.
To simplify the code for when the signal is fired, I am forcing all slots to be disconnected during this. This is different from boost::signals2, that does a copy of the list of slots before calling them in order to handle disconnections/connections while firing the signal.
The above works well for my scenario, where the signal of interest is fired very seldom (and in that case only once) but there are a lot of short-lived connections that otherwise use up a lot of memory even when using the trick outlined in the question.
For other scenarios, I've been able to replace the use of a signal with just a boost::function (thus requiring that there can only be a single connection) or just by sticking with the workaround in the question where the listener itself manages its lifetime.
I stumbled upon the same problem and i really miss some kind of explicit cleanup in the API.
In my scenario i am unloading some plug-in dll's and i have to assure there are no dangling objects (slots) which refer to code (vftables or whatsoever) living in the unloaded dll. Simply disconnecting slots didn't work due to the lazy deletion stuff.
My first workaround was a signal wrapper which tweaks the disconnecting code a little bit:
template <typename Signature>
struct MySignal
{
// ...
template <typename Slot>
void disconnect (Slot&& s)
{
mPrivate.disconnect (forward (s));
// connect/disconnect dummy slot to force cleanup of s
mPrivate.connect (&MySignal::foo);
mPrivate.disconnect (&MySignal::foo);
}
private:
// dummy slot function with matching signature
// ... foo (...)
private:
::boost::signals2::signal<Signature> mPrivate;
};
Unfortunately this didn't work because connect() only does some cleanup. It doesn't guarantee cleanup of all unconnected slots. Signal invocation on the other hand does a full cleanup but a dummy invocation would also be an unacceptable behavioral change (as already mentioned by others).
In the absence of alternatives i ended up in patching the original signal class (Edit: i really would appreciate a built-in solution. this patch was my last resort). My patch is around 10 lines of code and adds a public cleanup_connections() method to signal. My signal wrapper invokes the cleanup at the end of the disconnecting methods. This approach solved my problems and i didn't encounter any performance problems so far.
Edit: Here is my patch for boost 1.5.3
Index: signals2/detail/signal_template.hpp
===================================================================
--- signals2/detail/signal_template.hpp
+++ signals2/detail/signal_template.hpp
## -220,6 +220,15 ##
typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
do_disconnect(slot, is_group());
}
+ void cleanup_connections () const
+ {
+ unique_lock<mutex_type> list_lock(_mutex);
+ if(_shared_state.unique() == false)
+ {
+ _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
+ }
+ nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
+ }
// emit signal
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
## -690,6 +699,10 ##
{
(*_pimpl).disconnect(slot);
}
+ void cleanup_connections ()
+ {
+ (*_pimpl).cleanup_connections();
+ }
result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
{
return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));