From patchwork Tue Aug 3 15:34:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1512987 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=RJE+ZKzK; dkim-atps=neutral Received: from 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GfJyc1gR6z9sPf for ; Wed, 4 Aug 2021 01:42:00 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EC3D7395BC11 for ; Tue, 3 Aug 2021 15:41:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EC3D7395BC11 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1628005318; bh=1wjlUp8AgP+tECoQEIpKKPYShu5ey//LkuTpE553HR0=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=RJE+ZKzKIcgA9ioWGLN/hgzDg5d/rsx9C2JaBrkIY35EwhcmMwvlKUi8nBSEtt1Xt njGd/cBqeZMloetzgm9BleLukm2+Ec6bx493B/nqjjLRP4tTDf05UsduXTaPN+UvBj rV3GVFTVmgT2DqDhnE/y5szOyG9qK7y+A/hJsOT8= 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 E07973959E50 for ; Tue, 3 Aug 2021 15:34:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E07973959E50 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-522-EY-x2DrvN2eGCWUAQ1Is7w-1; Tue, 03 Aug 2021 11:34:27 -0400 X-MC-Unique: EY-x2DrvN2eGCWUAQ1Is7w-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 02ECC101C8A0; Tue, 3 Aug 2021 15:34:27 +0000 (UTC) Received: from localhost (unknown [10.33.36.118]) by smtp.corp.redhat.com (Postfix) with ESMTP id A32C1604CC; Tue, 3 Aug 2021 15:34:26 +0000 (UTC) Date: Tue, 3 Aug 2021 16:34:25 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Specialize allocator_traits> Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" This adds a partial specialization of allocator_traits, similar to what was already done for std::allocator. This means that most uses of polymorphic_allocator via the traits can avoid the metaprogramming overhead needed to deduce the properties from polymorphic_allocator. In addition, I'm changing polymorphic_allocator::delete_object to invoke the destructor (or pseudo-destructor) directly, rather than calling allocator_traits::destroy, which calls polymorphic_allocator::destroy (which is deprecated). This is observable if a user has specialized allocator_traits> and expects to see its destroy member function called. I consider explicit specializations of allocator_traits to be wrong-headed, and this use case seems unnecessary to support. So delete_object just invokes the destructor directly. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/std/memory_resource (polymorphic_allocator::delete_object): Call destructor directly instead of using destroy. (allocator_traits>): Define partial specialization. Tested powerpc64le-linux. Committed to trunk. commit 13a1ac9f6f700f4e214fcc83b122a4a405c6b13d Author: Jonathan Wakely Date: Tue Aug 3 14:00:47 2021 libstdc++: Specialize allocator_traits> This adds a partial specialization of allocator_traits, similar to what was already done for std::allocator. This means that most uses of polymorphic_allocator via the traits can avoid the metaprogramming overhead needed to deduce the properties from polymorphic_allocator. In addition, I'm changing polymorphic_allocator::delete_object to invoke the destructor (or pseudo-destructor) directly, rather than calling allocator_traits::destroy, which calls polymorphic_allocator::destroy (which is deprecated). This is observable if a user has specialized allocator_traits> and expects to see its destroy member function called. I consider explicit specializations of allocator_traits to be wrong-headed, and this use case seems unnecessary to support. So delete_object just invokes the destructor directly. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/std/memory_resource (polymorphic_allocator::delete_object): Call destructor directly instead of using destroy. (allocator_traits>): Define partial specialization. diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource index cdc5e5d98b1..6bca0afa018 100644 --- a/libstdc++-v3/include/std/memory_resource +++ b/libstdc++-v3/include/std/memory_resource @@ -232,7 +232,7 @@ namespace pmr void delete_object(_Up* __p) { - destroy(__p); + __p->~_Up(); deallocate_object(__p); } #endif // C++2a @@ -381,6 +381,136 @@ namespace pmr { return !(__a == __b); } #endif +} // namespace pmr + + /// Partial specialization for std::pmr::polymorphic_allocator + template + struct allocator_traits> + { + /// The allocator type + using allocator_type = pmr::polymorphic_allocator<_Tp>; + + /// The allocated type + using value_type = _Tp; + + /// The allocator's pointer type. + using pointer = _Tp*; + + /// The allocator's const pointer type. + using const_pointer = const _Tp*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /** @{ + * A `polymorphic_allocator` does not propagate when a + * container is copied, moved, or swapped. + */ + using propagate_on_container_copy_assignment = false_type; + using propagate_on_container_move_assignment = false_type; + using propagate_on_container_swap = false_type; + + static allocator_type + select_on_container_copy_construction(const allocator_type&) noexcept + { return allocator_type(); } + /// @} + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = false_type; + + template + using rebind_alloc = pmr::polymorphic_allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls `a.allocate(n)`. + */ + [[nodiscard]] static pointer + allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @return Memory of suitable size and alignment for `n` objects + * of type `value_type`. + * + * The third parameter is ignored.. + * + * Returns `a.allocate(n)`. + */ + [[nodiscard]] static pointer + allocate(allocator_type& __a, size_type __n, const_void_pointer) + { return __a.allocate(__n); } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls `a.deallocate(p, n)`. + */ + static void + deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + static void + construct(allocator_type& __a, _Up* __p, _Args&&... __args) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls `p->_Up()`. + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type&, _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } + + /** + * @brief The maximum supported allocation size + * @return `numeric_limits::max() / sizeof(value_type)` + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const allocator_type&) noexcept + { return size_t(-1) / sizeof(value_type); } + }; + +namespace pmr +{ /// Parameters for tuning a pool resource's behaviour. struct pool_options {