-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
std::function copies movable objects when is SOO is used #32472
Comments
I've tested with libc++=3.9.1-2 available in ubuntu zesty and it has the same problem. |
The SSO is only applied in this case because the copy constructor is noexcept. I need to do some further investigation to discover if libc++'s current behavior is legal, but I suspect it is. Even if the behavior is non-conforming, fixing this to behave as requested would take an ABI break. |
Yes, that's totally true. But my move constructor is noexcept too. So there is no reason to choose copy constructor over move constructor.
This is not always possible. In the part of the system where we've found the problem we use std::shared_ptr's. We can't change declaration of shared_ptr's copy constructor.
I think that this is covered by section 20.9.12.2.1 Effects: If !f, *this has no target; otherwise, move-constructs the target of f into the target of *this, leaving f in a valid state with an unspecified value. I'm not very good at reading standard and I may be mistaken. But even if current behavior is legal I still do not think that it is good and that it is not a flaw in standard. Though I agree, that such change will complicate std::function's code.
Why would it break ABI? I do not suggest to disable SOO, I suggest to use move constructor if it is available and marked as noexcept. Memory layout of std::function will not change. The only thing that will change is the constructor to be called. And that constructors will present in both old and new code, so no break here too. |
Good point, I hadn't considered that. It seems like you're relying on non-standard
You're not necessarily mistaken, but that language has since changed, and the change
This language makes it much clearer that Libc++'s behavior is legal.
I agree, it would be much better to perform a noexcept move operation in this case. The coset to make that change in Libc++ is very gerat because it means changing a vtable
std::function does type-erasure; Which is implemented using virtual functions. |
Thank you for clarifications. ABI breakage is a real stopper. |
Extended Description
Hi. Libc++ that comes with Xcode 8.2.1 has small object optimization implemented for std::function. But move constructor of std::function always uses copy constructor of the object. This results in unnecessary copies being made and additional destructor calls.
In our use case this even leads to crashes because the object is a handle and we rely that it will be destroyed on specific thread. But that extra copies, created while the std::function is dispatched to the worker thread, result in destructor being deleted at another time and from another thread.
It would be good if moving std::function object resulted in moving the underlying functor if it is movable.
I've attached a test program, that demonstrates the problem.
The text was updated successfully, but these errors were encountered: