I've recently started using Boost.Asio in a project and would like to know whether anyone knows a clean solution to transfer ownership of a newly created socket to tcp::acceptor::async_accept, which would in turn transfer this ownership to the accept handler function.
This isn't an incoherent desire, mind you, since the handler is to be called exactly once.
I have noticed I can't std::bind() an std::unique_ptr<> as parameter, since std::bind() requires its parameters to be CopyConstructible, and rightfully so. Not only that, but Boost's AcceptHandler concept is also required to be CopyConstructible.
So my options would be:
Go the deprecated std::auto_ptr<> way of moving objects with the copy constructor, potentially causing obscure bugs on new releases of Boost.Asio.
Use std::shared_ptr<> and have no way to take the shared ownership off the pointer once it's not needed anymore, i.e. when it reaches the actual handler function (this is how the job is done on the examples at http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/examples.html as far as I've read).
or
You have a better idea for me.
I'm pretty much at a loss here. Can anyone enlighten me?
I tried to find a way to do this using the c++0x standard library, but could not.
Eventually I settled on writing my own rvalue_reference_wrapper and rvalue_ref() convenience class. As per usual with std::bind, you need to wrap your non copyable object in something that is copyable (reference_wrapper is the best example). You could also have just passed a pointer, but that means changing your interface.
This worked on my machine:
#include <iostream>
#include <functional>
#include <memory>
template< class T >
struct rvalue_reference_wrapper
{
rvalue_reference_wrapper( T&& t )
: t_(std::move(t))
{}
operator T&&() const volatile
{
return std::move(t_);
}
private:
T&& t_;
};
template< class T >
rvalue_reference_wrapper<T> rvalue_ref( T&& t )
{
return rvalue_reference_wrapper<T>(std::move(t));
}
void go( std::unique_ptr<int> i )
{
std::cout << *i << std::endl;
}
int main()
{
std::unique_ptr<int> i(new int(1));
auto b = std::bind( go, rvalue_ref(std::move(i)) );
//auto b = std::bind( go, std::ref(std::move(i)) ); // Wont work
b();
}
I have not made the code bulletproof, but welcome some discussion about the need for an rvalue_reference_wrapper, or how to simulate one using std::reference_wrapper.
Also, for your specific case, you will likely need to write a difference version of rvalue_reference_wrapper, which holds the object by value not by rvalue reference, since your original unique_ptr is likely going to leave scope (and be destroyed) since you are using async asio calls.
Related
Problem: Unique_ptrs express ownership well, but cannot have their object lifetimes tracked by weak_ptrs. Shared_ptrs can be tracked by weak_ptrs but do not express ownership clearly.
Proposed solution: Derive a new pointer type (I'm going to call it strong_ptr) that is simply a shared_ptr but with the copy constructor and assignment operator deleted, so that it is hard to clone them. We then create another new borrowed_ptr type (which is not easily storable) to handle the temporary lifetime extension required when the weak_ptr accesses the object, and can thereby avoid using shared_ptrs explicitly anywhere.
This question Non-ownership copies of std::unique_ptr adn this one Better shared_ptr by distinct types for "ownership" and "reference"? are both similar but in both cases the choice is framed as simply unique_ptr vs shared_ptr and the answer does not propose a satisfactory solution to my mind. (Perhaps I should be answering those questions instead of asking a new one? Not sure what the correct etiquette is in this case.)
Here's a basic stab. Note that in order to avoid the user of the weak pointer having to convert to shared_ptr to use it, I create a borrowed_ptr type (thanks rust for the name) which wraps shared_ptr but makes it hard for the user to accidentally store it. So by using differently hamstrung shared_ptr derivatives we can express the intended ownership and guide the client code into correct usage.
#include <memory>
template <typename T>
// This owns the memory
class strong_ptr : public std::shared_ptr<T> {
public:
strong_ptr() = default;
strong_ptr(T* t) : std::shared_ptr<T>(t) {}
strong_ptr(const strong_ptr&) = delete;
strong_ptr& operator=(const strong_ptr&) = delete;
};
template <typename T>
// This can temporarily extend the lifetime but is intentionally hard to store
class borrowed_ptr : public std::shared_ptr<T> {
public:
borrowed_ptr() = delete;
borrowed_ptr(const borrowed_ptr&) = delete;
borrowed_ptr& operator=(const borrowed_ptr&) = delete;
template <typename T>
static borrowed_ptr borrow(const std::weak_ptr<T>& wp)
{
return wp.lock();
}
private:
borrowed_ptr(std::shared_ptr<T> &sp) : std::shared_ptr<T>(sp) {}
};
This seems fairly simple and an improvement over shared_ptr, but I cannot find any discussion of such a technique, so I can only imagine that I have missed an obvious flaw.
Can anyone give me a concrete reason why this is a bad idea? (And yes I know this is less efficient than unique_ptr - for PIMPL and so on I would still use unique_ptr.)
Caveat: I haven't yet used this in any more than a basic example, but this compiles and runs ok:
struct xxx
{
int yyy;
double zzz;
};
struct aaa
{
borrowed_ptr<xxx> naughty;
};
void testfun()
{
strong_ptr<xxx> stp = new xxx;
stp->yyy = 123;
stp->zzz = 0.456;
std::weak_ptr<xxx> wkp = stp;
// borrowed_ptr<xxx> shp = wkp.lock(); <-- Fails to compile as planned
// aaa badStruct { borrowed_ptr<xxx>::borrow(wkp) }; <-- Fails to compile as planned
// aaa anotherBadStruct; <-- Fails to compile as planned
borrowed_ptr<xxx> brp = borrowed_ptr<xxx>::borrow(wkp); // Only way to create the borrowed pointer
// std::cout << "wkp: " << wkp->yyy << std::endl; <-- Fails to compile as planned
std::cout << "stp: " << stp->yyy << std::endl; // ok
std::cout << "bp: " << brp->yyy << std::endl; // ok
}
Unique ownership is unique, full stop. One place owns this resource and will release it when that code so chooses.
Shared ownership is shared. Multiple places can own this resource, and the resource will only be released when all of them have done so. This is a binary state: either one place owns the resource or multiple places do.
Your ownership semantics are unique... except when they're not. And rules that work a certain way except when they don't are kind of problematic.
Now, your specific implementation is full of holes. shared/weak_ptr are all explicitly part of the interface of these types, so it is exceptionally easy to just get the shared_ptr out of a strong_ptr. If you have a weak_ptr to a strong_ptr (required for borrowed_ptr::borrow), then you could just lock it and get a shared_ptr.
But even if your interface were to properly hide all of this (that is, you make your own weak_ptr-equivalent type and you stop inheriting from shared_ptr), your API cannot stop someone from storing that borrowed_ptr anywhere they want. Oh sure, they can't change it later, but it's easy enough to store it in a class member at construction time or to heap allocate one or whatever.
So at the end of the day, locking a weak pointer still represents a claim of ownership. Therefore, the ownership semantics of your pointer stack is still shared; there's simply an API encouragement to not retain shared ownership for too long.
unique_ptr doesn't have "API encouragement"; it has API enforcement. That's what gives it unique ownership. C++ does not have a mechanism to create similar enforcement of the ownership semantics you want to create.
Encouragement may be useful on some level, but it'd probably be just as useful to just have borrowed_ptr as the encouragement for those who want to express that they are only claiming ownership temporarily. And just directly use shared/weak_ptr as normal otherwise. That is, your API should explicitly recognize that it is using shared ownership, so that nobody is fooled into thinking otherwise.
Maybe this question has been asked before, but I've never found a satisfactory answer. Also, for the purposes of simplicity assume I'm talking about a single-threaded application.
So, what I've heard a number of times is that if you have an object that is non-owned and whose lifetime is guaranteed, you should reference it with a raw pointer. The object's owner would use a unique_ptr, and hand out raw pointers as necessary.
But what if the object is non-owned, and the lifetime is not guaranteed? Then you can use a weak_ptr, yes. But then anyone who is handed a weak_ptr could be naughty and keep it locked, such that the object's owner can't cause the object to be destroyed. Sometimes this may not be a problem, but sometimes it is. For example, when the owned object represents some system resource which must be relinquished at a certain time.
You may say "well, then you should just make sure no one keeps the weak_ptr locked!" But that is just not ideal (in my opinion) from an OO design standpoint, as it creates a dependency between the "owner" object and any object that gets a weak_ptr from it. You might as well make the argument "you don't need to return const references; you should just make sure no one modifies the reference."
With Qt, you have the QPointer, which is basically what I'm looking for. It checks that the object hasn't been destroyed, but it can't prevent the object from being destroyed. I realize this isn't thread-safe, but again, I'm talking about the context of a single thread.
So why isn't there something similar for C++11? I'm sure I could make a wrapper around weak_ptr that accomplishes what I'm after. But I wonder if I'm going about this all wrong.
No. And it doesn't exist is because it's unsafe even for a single thread. Consider:
void some_function (super_weak_ptr foo)
{
foo->some_function();
}
What happens if some_function (through an indirect path) causes the object to be destroyed? And before you say that can never happen, yes it can. For example:
void got_some_data (some_type whatObject, some_other_type whatData)
{
super_weak_ptr object = findObject (whatObject);
if (object)
object->youGotMail (whatData);
}
Now, suppose the youGotMail function realizes that the object now got the last bit of data it needs and its job is complete, it might destroy that object, and now we're running a function on an object that no longer exists.
If you want a raw pointer, you know where to find one. It doesn't make much sense to create a "smart" pointer that's no safer than a raw pointer.
So if you're not managing the lifetime of an object, you need the ability to lock that object before you can do anything to that object.
You can do this with pure Standard C++ using shared_ptr<unique_ptr<T>>.
Observers received only a shared_ptr<const unique_ptr<T>>, allowing them to look but not touch. The owner, having a non-const smart pointer, can at any time call reset() on the unique_ptr to destroy the instance. At that time all the observers can also see that the unique_ptr has become empty.
Obvious threading and re-entrance caveats apply (you need to check the unique_ptr for having a valid pointer again after each callback you invoke, etc).
And if there should be multiple owners, it's a bit more work. You will need one shared_ptr<T*>, giving observers a shared_ptr<T* const>. And a separate shared_ptr<T> to manage the object lifetime. The shared_ptr<T*> will need to be manually filled with nullptr (The T*, not the shared_ptr) in the object's destructor.
There is no such thing, alas.
In 2009 I toyed with / explored such a smart pointer type that I called ZPtr, as I recall as a cleanup effort of some earlier code in that direction, in the context of supporting better file abstraction error handling than the silence treatment of the standard library's iostreams. The (earlier) idea was to not have any zombie objects around, by self-destroying when no further meaningful operations were possible, and this required access via a smart pointer that could detect the existence or not of the referent. Evidently it was not such a good idea at the time, because the article I sent to DDJ about it was rejected … by the silence treatment.
I think now that we have argument forwarding support in the language, the time for such a pointer may have come. It would be even better with possible overloading of the . operator. But the functionality will anyway have to be chosen very carefully.
The std::weak_ptr isn't really "locked", in spite of naming. It's just used to obtain a std::shared_ptr, if possible. And a std::shared_ptr readily supplies you with a raw pointer.
So you can choose to hand out not std::weak_ptr directly, but a wrapper that only provides a temporary raw pointer.
It will not be very thread safe though, and unlike a ZPtr it will not give the client code any idea of why the referent doesn't exist any more (when it doesn't). But it just may be all that you need. Let me get some coffee & a bite to eat, then I'll cook up an example.
Example:
#include <memory>
namespace cppx {
using std::shared_ptr;
using std::weak_ptr;
template< class Type >
class Poor_ptr
{
private:
struct Null {};
weak_ptr<Type> weak_p_;
public:
explicit operator bool() const { return not is_null(); }
friend
auto operator==( const Poor_ptr& p, Poor_ptr::Null* )
-> bool
{ return p.is_null(); }
friend
auto operator==( Poor_ptr::Null*, const Poor_ptr& p )
-> bool
{ return p.is_null(); }
friend
auto operator!=( const Poor_ptr& p, Poor_ptr::Null* )
-> bool
{ return not p.is_null(); }
friend
auto operator!=( Poor_ptr::Null*, const Poor_ptr& p )
-> bool
{ return not p.is_null(); }
auto is_null() const
-> bool
{ return (ptr_or_null() == nullptr); }
auto ptr_or_null() const
-> Type*
{
try
{
return weak_p_.lock().get();
}
catch( ... )
{
return nullptr;
}
}
auto ptr() const
-> Type*
{ return weak_p_.lock().get(); }
Poor_ptr( shared_ptr< Type > p )
: weak_p_( p )
{}
};
} // namespace cppx
#include <iostream>
using namespace std;
auto main() -> int
{
cout << boolalpha;
auto p = make_shared<int>( 42 );
cppx::Poor_ptr<int> pp = p;
cout
<< "That " << pp.ptr_or_null() << " is null is "
<< (pp == 0) << ", not " << !!pp << ".\n";
p.reset();
cout
<< "That " << pp.ptr_or_null() << " is null is "
<< (pp == 0) << ", not " << !!pp << ".\n";
}
Oh, and to cover the problem that David Schwartz mentions, that of the object disappearing in mid-call of some function, you can just provide a member function that executes a functor such as std::function with a raw pointer as argument, where the referred to object is guaranteed kept alive during that call (namely by having a local std::shared_ptr).
Then the client code programmer can choose whether to rely on an assumption that called functions will not destroy the object, or use the safer callback mechanism.
To save some code lets say I have a custom allocator named MyAlloc which I have successfully used with a std::vector<int> as follows:
std::vector<int,MyAlloc<int>> vec;
now I want to save a lambda in a std::function using the custom allocator, how do I do it?
My failed attempt:
int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
//...
});
Update: allocators in std::function have been deprecated
According to the standard, you need to give a tag type as the first argument to indicate that you want to use a custom allocator:
std::function<void(int)> f(std::allocator_arg, MyAlloc<char>{}, [i](int in){
//...
});
As pointed out by #Casey and #Potatoswatter in the comments, the template argument type given to the allocator does not matter, as long as it's an object type. So char is fine here.
Update for C++17: It turns out that the allocator support for std::function has a number of fundamental issues, which lead to it being deprecated in C++17. If you nonetheless insist on using it, be sure to carefully check your implementation before doing so. GCC's standard library never implemented those functions, but even if your standard library does, it might not behave the way that you expect.
I realize this was answered properly, but even after reading this article and the replies I struggled a bit getting the syntax correct trying to overload an allocator for std::function that cross compiles on X64, PS4, and Xbox One in VS2012.
If it's not clear to the reader you will need to declare an allocator class per Casey's comment. Although this is fairly obvious if you read all the replies, what wasn't clear was the way these allocators are passed to the object which isn't like most of the STL allocators I've used before which take an allocator type (not instance) as part of the type specification.
For std::function an instantiated allocator is supplied to the constructor of your std::function object, which is what ComicSansMS is showing above.
For using this with a member function instead of the lambda code shown in this sample, it gets a bit tricky:
#include <functional>
MyAllocType g_myAlloc; // declared somewhere and globally instantiated to persist
// sample of a member function that takes an int parameter
class MyClassType
{
public:
void TestFunction( int param )
{
}
};
MyClassType MyClass; // instantiated object
// example without allocator
// note the pointer to the class type that must precede function parameters since
// we are using a method. Also std::mem_fn is require to compile in VS2012 :/
std::function<void(MyClassType*, int)> f( std::mem_fn( &MyClassType::TestFunction ) );
// usage of function needs an instantiated object (perhaps there is a way around this?)
f( &MyClass, 10 );
// example with allocator
std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );
// usage of function is the same as above and needs an instantiated object
f( &MyClass, 10 );
//or a non member function, which is much cleaner looking
void NonMemberFunction( int param )
{
}
std::function<void(int)> f(std::allocator_arg, g_myAlloc, NonMemberFunction);
Hope this helps people, it took me longer than I'd like to admit to get this working, and as much as I use this site I figured I'd leave a comment here if for no one other than myself on how to use it. :)
2 final questions to those that are smarter than myself:
Q: Is there a way to include the allocator as part of the type?
Q: Is there a way to use a member function without an instance of an object?
To update this, if you decide to pass one of these std::function objects around as a parameter to some other function, I found I needed to use std::function::assign, or else the assignment results in a shallow copy. This can be a problem if you are trying to pass it along to an object with a longer lifecycle than the original.
Example:
std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );
void FunctionTakeParam( std::function<void(MyClassType*, int)> &FunctionIn )
{
// this results in a reallocation using your allocator
std::function<void(MyClassType*, int)> MyLocalFunction.assign( std::allocator_arg, g_myAlloc, FunctionIn );
// the below results in a shallow copy which will likely cause bad things
//std::function<void(MyClassType*, int)> MyLocalFunction( std::allocator_arg, g_myAlloc, FunctionIn );
...
}
Recently i started to work on one legacy project and trying to fix segfaults (double delete). Many of them is happening on boost::shared_ptr destructor or operator=(on objects that contain a shared_ptr). The code contains is massive usage of shared_ptr-s, including copying, reset()-ing, assigning etc. According to boost docs we have not valid usage - its not safe to destruct/copy/reset same shared_ptr in many threads.
Locking each time seems impossible, so im searching for drop-in replacement for boost::shared_ptr. So the question is: if i replace all boost::shared_ptr with std::shared_ptr or std::tr1::shared_ptr will the solve this issue? Seems tr1 is safer version but its not clear for me. Second question - is c++0x version any better than tr1 ? (note we have gcc 4.4.6 and cannot upgrade it)
Accoring to gcc docs, c++11 std::shared_ptr should fix that, but im not sure about gcc4.4 version...
UPD: Just maked experiment and now i know all 3 implementations do segfault on this code(gcc 4.4).. seems i should make custom class or maybe other workaround...
#include <iostream>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<int> ptrtype;
ptrtype p(new int);
void test() {
for(long i=0; i<1000000; ++i) {
ptrtype p1 = p;
p = ptrtype();
p.reset( new int );
}
}
int main() {
boost::thread_group tg;
for(int i=0; i<100; ++i) tg.add_thread( new boost::thread(test) );
tg.join_all();
std::cout << "Normal exit\n";
return 0;
}
Step 1: Build a class like this, and replace usage of boost::shared_ptr<T> with it.
template<typename T>
struct trivial_ptr {
T* t;
template<typename U>
void reset( U* p ) {t=p;}
void reset( T* p = NULL ) { t=p; }
template<typename U>
trivial_ptr<T>& operator=(trivial_shared_ptr<U>const& o) {
t = o.t;
return *t;
}
explicit trivial_ptr( T* p ):t(p) {}
...
};
this class is not intended to run, but just to compile with the correct interface. Once you have compiled, you can ensure you know what parts of the boost::shared_ptr interface you are using. (Are you using custom deleters? etc -- the problem could be harder, or easier, and the above can help test it)
Once you are there, you can work out how hard it will be to write up a shared_ptr<T> that handles multiple threads accessing the same variable at the same time.
Now, this is extremely messy. If one thread resets a given shared_ptr while another thread reads from it, the pointer read from may be completely invalid by the time the reading thread has access to it. In effect, you need to guard all access to the underlying pointer in a mutex, which is utterly impractical.
On the other hand, if what you have is multiple readers, and never a reader and a writer, you are in better shape -- in theory, you could fix the problem with the use of appropriate locks on the reference count code.
However, what you actually describe seems to involve multiple threads both reading and writing to the same variable. And that is fundamentally broken in a way that mere thread safety on the shared_ptr variable is not going to fix.
The problem you appear to have is attempting to modify the same instance of a variable in two separate threads (AKA a data race). shared_ptr is no more protected against this than int's are. Your reference to the gcc docs says the same thing ("same level of thread safety as built-in types"). Attempting to modify the same instance of a shared_ptr in two different threads requires some sort of synchronization to prevent the data race. Attempting to modify two different instances of a shared_ptr that are pointing to the same object is OK (no data race, or shared_ptr must implement whatever is necessary to prevent a data race internally). Attempting to modify the object that they point to is also a data race.
std::shared_ptr may use atomic ints if the compiler/architecture/implementation supports/use it. But i wouldn't bet on it, and doing so will make your code less portable. But it may work as a temporary workaround (e.g. to have a running program so you understand what the code is supposed to do).
Writing your own shared_ptr wrapper might be an option, but your code will still need to be audited for deadlocks.
Is there a stock no-op deallocator in Boost to use with boost::shared_ptr for static objects, etc.
I know it's ultra-trivial to write, but I don't want to sprinkle my code with extra tiny functions if there is already one available.
Yes there is one here:
#include <boost/serialization/shared_ptr.hpp> // for null_deleter
class Foo
{
int x;
};
Foo foo;
boost::shared_ptr< Foo > sharedfoo( &foo, boost::serialization::null_deleter() );
There is, of course, a danger with the fact that you need to know the function you call doesn't store the shared_ptr for later use, as it actually goes against the policy of shared_ptr in that the underlying object remains valid until that of the last instance of the shared_ptr.
Solution uses Boost.Lambda:
#include <boost/shared_ptr.hpp>
#include <boost/lambda/lambda.hpp>
int main()
{
int *p = new int(5);
{
boost::shared_ptr<int> sp(p, boost::lambda::_1);
}
delete p;
}
'boost::lambda::_1' creates an empty functor that takes one argument.
You'll probably want to put a //comment in there to let people know why you did it, though.
If Boost <= 1.54, use boost/log/utility/empty_deleter.hpp.
If Boost == 1.55, use boost/utility/empty_deleter.hpp.
If Boost >= 1.56, use boost/core/null_deleter.hpp.
Wouldn't it be cleaner just to take an extra reference so the deallocator is never called? (Although that's still not very clean.)
I can't say that there's no function in Boost which would do the job, but it doesn't sound like something they would want to include.
EDIT: Having read the comments and a little documentation, it boils down to this:
Reference leaking. At some point, execute this:
new shared_ptr( my_global_shared_ptr );
Advantages: conceptually easy. Disadvantages: you are leaking something on the heap.
Custom deallocator. Since shared_ptr requires little of the deallocator function, an anonymous identity function like that provided in the other answer would do fine.
Advantages: leverages Boost and has absolutely no overhead. Disdvantages: requires a little documentation.
Non-static global object. If there is a global shared_ptr for your object, that should be the only means of access to it. Replace the declaration of the global with a shared_ptr intialized by new my_class. I think this is best.
There's a ticket for this on the Boost bug tracker: https://svn.boost.org/trac/boost/ticket/1913 - no activity for a long time until some murmur two weeks ago.
FWIW, this what I'm using.
I use it in unit tests to adapt a local into a shared_ptr.
// The class NoOp_sptr_Deleter can be used to construct a shared_ptr<>()
// that will NOT delete the pointee.
// This can be helpful in unit-testing. Wrapping a local as a shared_ptr.
// Do take care with the lifetimes though.
struct NoOp_sptr_Deleter
{
void operator()(void const *) const {}
};
template<typename T>
boost::shared_ptr<T> FakeSharedPtrFromRef(T& aRef)
{
return boost::shared_ptr<T>(&aRef, NoOp_sptr_Deleter() );
}