]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Optimize std::function move constructor [PR101923]
authorJonathan Wakely <jwakely@redhat.com>
Tue, 17 Aug 2021 10:30:56 +0000 (11:30 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 17 Aug 2021 13:22:50 +0000 (14:22 +0100)
PR 101923 points out that the unconditional swap in the std::function
move constructor makes it slower than copying an empty std::function.
The copy constructor has to check for the empty case before doing
anything, and that makes it very fast for the empty case.

Adding the same check to the move constructor avoids copying the
_Any_data POD when we don't need to. We can also inline the effects of
swap, by copying each member and then zeroing the pointer members.

This makes moving an empty object at least as fast as copying an empty
object.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:

PR libstdc++/101923
* include/bits/std_function.h (function(function&&)): Check for
non-empty parameter before doing any work.

libstdc++-v3/include/bits/std_function.h

index c08484465c95bb8b71d7a4e3010541040995d649..fb86ff1c5f84ebdc487c260ad8c9fa85dd11ca83 100644 (file)
@@ -389,8 +389,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  (if it has one).
        */
       function(function&& __x) noexcept
-      : _Function_base()
-      { __x.swap(*this); }
+      : _Function_base(), _M_invoker(__x._M_invoker)
+      {
+       if (static_cast<bool>(__x))
+         {
+           _M_functor = __x._M_functor;
+           _M_manager = __x._M_manager;
+           __x._M_manager = nullptr;
+           __x._M_invoker = nullptr;
+         }
+      }
 
       /**
        *  @brief Builds a %function that targets a copy of the incoming