From patchwork Fri Nov 8 15:30:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 2008595 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=K6srQEa/; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XlNfQ3236z1xyp for ; Sat, 9 Nov 2024 02:49:18 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 876233857823 for ; Fri, 8 Nov 2024 15:49:16 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id BCED03858433 for ; Fri, 8 Nov 2024 15:46:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BCED03858433 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BCED03858433 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1731080775; cv=none; b=o13G9L48MLsrF4DVKtRE1QoIKcRnSKDByLzs3RXKRyEfmlUr1hlsmDQ4QiTGYYkikBGZY9Zhjxx7LVlTY23SZx/TP/QGmyItCts2tOJrr/0cH27CAmY3Ht6LLJHMR9nfoXZfd/LTD+l7E9wrrgoLVZe5QM1ws0btYvmO9QkbCpU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1731080775; c=relaxed/simple; bh=7exCvjHFgwrJ2INLSYsCgVYTPMdryAQxntSyjs2t7mM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=VhlTg4hv52DQl6C7ATFEtY7XlkbntAz6D6vDsP69RiQhglcSQ1O0QfVhXrKiycnJcUA0fnwrnPbghPgN5JPUmBSOlhSQuuyGVq3PP6NKE1eCedcBfLRfp1IJYE8lydbGAJ3NOANgFvfDu4CmNKMfTx3ZBB9Nw2XofFk2AlPw3XI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1731080772; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mSLZe+xpg0/fGVl5cBDXKSA1DZjnHrFLaaAXdB6B7v0=; b=K6srQEa/7p19eluqbhKzbm4XB9m+iYKaDbZidRgwD62kUEC5k2Q442oOP/OI5KUm5en1hd NbME19HYieqT9EOAPCTPzTSqOmE0l7jPS87f4MLN3RTTNPOUdbiVQoJSg9GJOJYEritolD fPjh9iaaoB2TJEuPyKdgc70xBw1BbIY= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-688-LzAxesXVOAmQoOOiwFeuOg-1; Fri, 08 Nov 2024 10:46:09 -0500 X-MC-Unique: LzAxesXVOAmQoOOiwFeuOg-1 X-Mimecast-MFC-AGG-ID: LzAxesXVOAmQoOOiwFeuOg Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 128A41955F43; Fri, 8 Nov 2024 15:46:03 +0000 (UTC) Received: from localhost (unknown [10.22.64.104]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 37917300019E; Fri, 8 Nov 2024 15:46:01 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: =?utf-8?q?Fran=C3=A7ois_Dumont?= Subject: [PATCH 02/12] libstdc++: Allow unordered_set assignment to assign to existing nodes Date: Fri, 8 Nov 2024 15:30:12 +0000 Message-ID: <20241108154548.813315-3-jwakely@redhat.com> In-Reply-To: <20241108154548.813315-1-jwakely@redhat.com> References: <20241108154548.813315-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: NoIZjJZ0kep5f9CFr-YB2YbWQTIAwN5oInYjW-uCqIg_1731080768 X-Mimecast-Originator: redhat.com X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Currently the _ReuseOrAllocNode::operator(Args&&...) function always destroys the value stored in recycled nodes and constructs a new value. The _ReuseOrAllocNode type is only ever used for implementing assignment, either from another unordered container of the same type, or from std::initializer_list. Consequently, the parameter pack Args only ever consists of a single parameter or type const value_type& or value_type. We can replace the variadic parameter pack with a single forwarding reference parameter, and when the value_type is assignable from that type we can use assignment instead of destroying the existing value and then constructing a new one. Using assignment is typically only possible for sets, because for maps the value_type is std::pair and in most cases std::is_assignable_v is false. libstdc++-v3/ChangeLog: * include/bits/hashtable_policy.h (_ReuseOrAllocNode::operator()): Replace parameter pack with a single parameter. Assign to existing value when possible. * testsuite/23_containers/unordered_multiset/allocator/move_assign.cc: Adjust expected count of operations. * testsuite/23_containers/unordered_set/allocator/move_assign.cc: Likewise. Reviewed-by: François Dumont --- libstdc++-v3/include/bits/hashtable_policy.h | 37 +++++++++++++------ .../allocator/move_assign.cc | 5 ++- .../unordered_set/allocator/move_assign.cc | 10 +++-- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index b5f837e6061..7a3c66c37fd 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -172,24 +172,39 @@ namespace __detail ~_ReuseOrAllocNode() { _M_h._M_deallocate_nodes(_M_nodes); } - template +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr + template __node_ptr - operator()(_Args&&... __args) + operator()(_Arg&& __arg) { if (!_M_nodes) - return _M_h._M_allocate_node(std::forward<_Args>(__args)...); + return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); + + using value_type = typename _NodeAlloc::value_type::value_type; __node_ptr __node = _M_nodes; - _M_nodes = _M_nodes->_M_next(); - __node->_M_nxt = nullptr; - auto& __a = _M_h._M_node_allocator(); - __node_alloc_traits::destroy(__a, __node->_M_valptr()); - _NodePtrGuard<__hashtable_alloc, __node_ptr> __guard { _M_h, __node }; - __node_alloc_traits::construct(__a, __node->_M_valptr(), - std::forward<_Args>(__args)...); - __guard._M_ptr = nullptr; + if constexpr (is_assignable::value) + { + __node->_M_v() = std::forward<_Arg>(__arg); + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + } + else + { + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + auto& __a = _M_h._M_node_allocator(); + __node_alloc_traits::destroy(__a, __node->_M_valptr()); + _NodePtrGuard<__hashtable_alloc, __node_ptr> + __guard{ _M_h, __node }; + __node_alloc_traits::construct(__a, __node->_M_valptr(), + std::forward<_Arg>(__arg)); + __guard._M_ptr = nullptr; + } return __node; } +#pragma GCC diagnostic pop private: __node_ptr _M_nodes; diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/allocator/move_assign.cc index 50608ec443f..6d00354902e 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/allocator/move_assign.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/allocator/move_assign.cc @@ -46,8 +46,9 @@ void test01() VERIFY( 1 == v1.get_allocator().get_personality() ); VERIFY( 2 == v2.get_allocator().get_personality() ); - VERIFY( counter_type::move_count == 1 ); - VERIFY( counter_type::destructor_count == 2 ); + VERIFY( counter_type::move_count == 0 ); + // 1 element in v1 destroyed. + VERIFY( counter_type::destructor_count == 1 ); } void test02() diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc index 677ea67d0ea..6be70022705 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/move_assign.cc @@ -52,8 +52,9 @@ void test01() VERIFY( 1 == v1.get_allocator().get_personality() ); VERIFY( 2 == v2.get_allocator().get_personality() ); - VERIFY( counter_type::move_count == 1 ); - VERIFY( counter_type::destructor_count == 2 ); + VERIFY( counter_type::move_count == 0 ); + // 1 element in v1 destroyed. + VERIFY( counter_type::destructor_count == 1 ); } // Check there's nothing left allocated or constructed. @@ -130,8 +131,9 @@ void test03() VERIFY( 1 == v1.get_allocator().get_personality() ); VERIFY( 2 == v2.get_allocator().get_personality() ); - VERIFY( counter_type::move_count == 1 ); - VERIFY( counter_type::destructor_count == i + 1 ); + VERIFY( counter_type::move_count == 0 ); + // (i - 1) elements in v2 destroyed, and 1 element in v1 destroyed. + VERIFY( counter_type::destructor_count == i ); } // Check there's nothing left allocated or constructed.