From c3e1e405b2c8a0cc2d058722673ac6ee4c1eaa36 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 28 Apr 2016 10:30:29 -0400 Subject: [PATCH] remove variadic template emulation for c++98, and introduce emplace_back to heterogeneous_queue as well, to avoid all moves of alert objects (#658) --- include/libtorrent/Makefile.am | 1 - include/libtorrent/alert_manager.hpp | 17 +----- .../aux_/alert_manager_variadic_emplace.hpp | 55 ------------------- include/libtorrent/heterogeneous_queue.hpp | 10 ++-- test/test_heterogeneous_queue.cpp | 38 ++++++------- 5 files changed, 26 insertions(+), 95 deletions(-) delete mode 100644 include/libtorrent/aux_/alert_manager_variadic_emplace.hpp diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 7599e9356..e5fce67ff 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -159,7 +159,6 @@ nobase_include_HEADERS = \ tommath_class.h \ tommath_superclass.h \ \ - aux_/alert_manager_variadic_emplace.hpp \ aux_/array_view.hpp \ aux_/allocating_handler.hpp \ aux_/bind_to_device.hpp \ diff --git a/include/libtorrent/alert_manager.hpp b/include/libtorrent/alert_manager.hpp index e90cecd55..6216f68eb 100644 --- a/include/libtorrent/alert_manager.hpp +++ b/include/libtorrent/alert_manager.hpp @@ -58,9 +58,6 @@ POSSIBILITY OF SUCH DAMAGE. #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -// used for emplace_alert() variadic template emulation for c++98 -#define TORRENT_ALERT_MANAGER_MAX_ARITY 7 - namespace libtorrent { #ifndef TORRENT_DISABLE_EXTENSIONS @@ -74,8 +71,6 @@ namespace libtorrent { , boost::uint32_t alert_mask = alert::error_notification); ~alert_manager(); -#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES - template void emplace_alert(Args&&... args) { @@ -95,20 +90,12 @@ namespace libtorrent { * (1 + T::priority)) return; - T alert(m_allocations[m_generation], std::forward(args)...); - m_alerts[m_generation].push_back(alert); + T& alert = m_alerts[m_generation].emplace_back( + m_allocations[m_generation], std::forward(args)...); maybe_notify(&alert, lock); } -#else - -// emulate variadic templates for c++98 - -#include "libtorrent/aux_/alert_manager_variadic_emplace.hpp" - -#endif - bool pending() const; void get_all(std::vector& alerts); diff --git a/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp b/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp deleted file mode 100644 index 5c360eb40..000000000 --- a/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp +++ /dev/null @@ -1,55 +0,0 @@ - -#if !defined BOOST_PP_IS_ITERATING || !BOOST_PP_IS_ITERATING -// set-up iteration - -#include -#include -#include -#include - -#define BOOST_PP_ITERATION_PARAMS_1 \ - (3, (0, TORRENT_ALERT_MANAGER_MAX_ARITY, \ - "libtorrent/aux_/alert_manager_variadic_emplace.hpp")) -#include BOOST_PP_ITERATE() - - -#else // BOOST_PP_IS_ITERATING - -// loop body - -#define I BOOST_PP_ITERATION() - - template - void emplace_alert(BOOST_PP_ENUM_BINARY_PARAMS(I, A, const& a) ) - { - mutex::scoped_lock lock(m_mutex); -#ifndef TORRENT_NO_DEPRECATE - if (m_dispatch) - { - m_dispatch(std::auto_ptr(new T(m_allocations[m_generation] - BOOST_PP_COMMA_IF(I) - BOOST_PP_ENUM_PARAMS(I, a)))); - return; - } -#endif - // don't add more than this number of alerts, unless it's a - // high priority alert, in which case we try harder to deliver it - // for high priority alerts, double the upper limit - if (m_alerts[m_generation].size() >= m_queue_size_limit - * (1 + T::priority)) - return; - - T alert(m_allocations[m_generation] - BOOST_PP_COMMA_IF(I) - BOOST_PP_ENUM_PARAMS(I, a)); - m_alerts[m_generation].push_back(alert); - - maybe_notify(&alert, lock); - } - -#undef I - -#endif - diff --git a/include/libtorrent/heterogeneous_queue.hpp b/include/libtorrent/heterogeneous_queue.hpp index bed8c2bee..805803e9c 100644 --- a/include/libtorrent/heterogeneous_queue.hpp +++ b/include/libtorrent/heterogeneous_queue.hpp @@ -53,10 +53,9 @@ namespace libtorrent { , m_num_items(0) {} - // TODO: 2 add emplace_back() version - template - typename boost::enable_if >::type - push_back(U const& a) + template + typename boost::enable_if, U&>::type + emplace_back(Args&&... args) { // the size of the type rounded up to pointer alignment const int object_size = (sizeof(U) + sizeof(*m_storage) - 1) @@ -75,12 +74,13 @@ namespace libtorrent { ptr += header_size; // construct in-place - new (ptr) U(a); + new (ptr) U(std::forward(args)...); // if we constructed the object without throwing any exception // update counters to indicate the new item is in there ++m_num_items; m_size += header_size + object_size; + return *reinterpret_cast(ptr); } void get_pointers(std::vector& out) diff --git a/test/test_heterogeneous_queue.cpp b/test/test_heterogeneous_queue.cpp index 32543121a..588049a31 100644 --- a/test/test_heterogeneous_queue.cpp +++ b/test/test_heterogeneous_queue.cpp @@ -138,24 +138,24 @@ private: F& operator=(F const& f); }; -// test push_back of heterogeneous types +// test emplace_back of heterogeneous types // and retrieval of their pointers -TORRENT_TEST(push_back) +TORRENT_TEST(emplace_back) { using namespace libtorrent; heterogeneous_queue q; - q.push_back(B(0, 1)); + q.emplace_back(0, 1); TEST_EQUAL(q.size(), 1); - q.push_back(B(2, 3)); + q.emplace_back(2, 3); TEST_EQUAL(q.size(), 2); - q.push_back(B(4, 5)); + q.emplace_back(4, 5); TEST_EQUAL(q.size(), 3); - q.push_back(C(6, 7)); + q.emplace_back(6, 7); TEST_EQUAL(q.size(), 4); - q.push_back(C(8, 9)); + q.emplace_back(8, 9); TEST_EQUAL(q.size(), 5); - q.push_back(C(10, 11)); + q.emplace_back(10, 11); TEST_EQUAL(q.size(), 6); std::vector ptrs; @@ -196,13 +196,13 @@ TORRENT_TEST(swap) heterogeneous_queue q1; heterogeneous_queue q2; - q1.push_back(B(0, 1)); - q1.push_back(B(2, 3)); - q1.push_back(B(4, 5)); + q1.emplace_back(0, 1); + q1.emplace_back(2, 3); + q1.emplace_back(4, 5); TEST_EQUAL(q1.size(), 3); - q2.push_back(C(6, 7)); - q2.push_back(C(8, 9)); + q2.emplace_back(6, 7); + q2.emplace_back(8, 9); TEST_EQUAL(q2.size(), 2); std::vector ptrs; @@ -245,13 +245,13 @@ TORRENT_TEST(destruction) heterogeneous_queue q; TEST_EQUAL(D::instances, 0); - q.push_back(D()); + q.emplace_back(); TEST_EQUAL(D::instances, 1); - q.push_back(D()); + q.emplace_back(); TEST_EQUAL(D::instances, 2); - q.push_back(D()); + q.emplace_back(); TEST_EQUAL(D::instances, 3); - q.push_back(D()); + q.emplace_back(); TEST_EQUAL(D::instances, 4); q.clear(); @@ -269,7 +269,7 @@ TORRENT_TEST(copy_move) // make sure the queue has to grow at some point, to exercise its // copy/move of elements for (int i = 0; i < 1000; ++i) - q.push_back(F(i)); + q.emplace_back(i); std::vector ptrs; q.get_pointers(ptrs); @@ -293,7 +293,7 @@ TORRENT_TEST(nontrivial) heterogeneous_queue q; for (int i = 0; i < 10000; ++i) { - q.push_back(E("testing to allocate non-trivial objects")); + q.emplace_back("testing to allocate non-trivial objects"); } }