From patchwork Mon Nov 17 10:41:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 411497 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3FB8A14003E for ; Mon, 17 Nov 2014 21:41:54 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; q=dns; s=default; b=DgJAbETQ71nQDb8mhrlx/Ipa29fIxl tysgjJ4vn8ab8r5ArG+2JLHvOhj3ic9uvGOrYjQzG0e2LOVan4P1tufIx8IXTOxX NoNZ2xe8q58i1PXpAlEKC3YyKve7wjKkvgKTM/uhRQU5bpJDtFecz0RkSGzRlBSn +VkCLOSE7Hv18= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; s=default; bh=sJwL8eOHQ8RZm4MkQy65ZGquI4c=; b=iz3z xdSEiyNcX7UvtGtfVHU9zt7ulOQOBfmlR7BjQYI9TerulMEwnA8ZuriDHL5PAjZ1 TFD8oocEbhR/+Urf8sJVP10d2bWPTdFKrtu2wJwIvrLW65Szoc3UVDdwvXa6Jv+c wdGaVsSAuyLsI0Sk05mI9J1tbBTR91SlJy0RAA8= Received: (qmail 7327 invoked by alias); 17 Nov 2014 10:41:46 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 7296 invoked by uid 89); 17 Nov 2014 10:41:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 17 Nov 2014 10:41:43 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sAHAfgjf008621 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 17 Nov 2014 05:41:42 -0500 Received: from localhost (ovpn-116-136.ams2.redhat.com [10.36.116.136]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sAHAffjq026039; Mon, 17 Nov 2014 05:41:41 -0500 Date: Mon, 17 Nov 2014 10:41:40 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: Re: [patch] New std::string implementation Message-ID: <20141117104140.GP5191@redhat.com> References: <20141114154330.GH5191@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20141114154330.GH5191@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) On 14/11/14 15:43 +0000, Jonathan Wakely wrote: >This is the long-awaited ABI break for std::string, replacing our >venerable Copy-On-Write implementation with a C++11-conforming >Small-String-Optimization implementation (based on Paolo's vstring). This patch fixes move construction and assignment in . I'm still trying to fix the locale facet instantiations. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 66560d2..ebcc462 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -471,7 +471,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_capacity(__str._M_allocated_capacity); } - _M_set_length(__str.length()); + // Must use _M_length() here not _M_set_length() because + // basic_stringbuf relies on writing into unallocated capacity so + // we mess up the contents if we put a '\0' in the string. + _M_length(__str.length()); __str._M_data(__str._M_local_data()); __str._M_set_length(0); } diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream index be44dae..1940ddd 100644 --- a/libstdc++-v3/include/std/sstream +++ b/libstdc++-v3/include/std/sstream @@ -64,6 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class _GLIBCXX_DEFAULT_ABI_TAG basic_stringbuf : public basic_streambuf<_CharT, _Traits> { + struct __xfer_bufptrs; public: // Types: typedef _CharT char_type; @@ -118,9 +119,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_stringbuf(const basic_stringbuf&) = delete; basic_stringbuf(basic_stringbuf&& __rhs) - : __streambuf_type(static_cast(__rhs)), - _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string)) - { __rhs._M_stringbuf_init(__rhs._M_mode); } + : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this)) + { __rhs._M_sync(const_cast(__rhs._M_string.data()), 0, 0); } // 27.8.2.2 Assign and swap: @@ -130,18 +130,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_stringbuf& operator=(basic_stringbuf&& __rhs) { + __xfer_bufptrs __st{__rhs, this}; const __streambuf_type& __base = __rhs; __streambuf_type::operator=(__base); this->pubimbue(__rhs.getloc()); _M_mode = __rhs._M_mode; _M_string = std::move(__rhs._M_string); - __rhs._M_stringbuf_init(__rhs._M_mode); + __rhs._M_sync(const_cast(__rhs._M_string.data()), 0, 0); return *this; } void swap(basic_stringbuf& __rhs) { + __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)}; + __xfer_bufptrs __r_st{__rhs, this}; __streambuf_type& __base = __rhs; __streambuf_type::swap(__base); __rhs.pubimbue(this->pubimbue(__rhs.getloc())); @@ -288,6 +291,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // interface of basic_streambuf, taking just an int. void _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off); + + private: +#if __cplusplus >= 201103L +#if _GLIBCXX_USE_CXX11_ABI + // This type captures the state of the gptr / pptr pointers as offsets + // so they can be restored in another object after moving the string. + struct __xfer_bufptrs + { + __xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to) + : _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1} + { + const _CharT* __str = __from._M_string.data(); + if (__from.eback()) + { + _M_goff[0] = __from.eback() - __str; + _M_goff[1] = __from.gptr() - __str; + _M_goff[2] = __from.egptr() - __str; + } + if (__from.pbase()) + { + _M_poff[0] = __from.pbase() - __str; + _M_poff[1] = __from.pptr() - __from.pbase(); + _M_poff[2] = __from.epptr() - __str; + } + } + + ~__xfer_bufptrs() + { + char_type* __str = const_cast(_M_to->_M_string.data()); + if (_M_goff[0] != -1) + _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]); + if (_M_poff[0] != -1) + _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]); + } + + basic_stringbuf* _M_to; + off_type _M_goff[3]; + off_type _M_poff[3]; + }; +#else + // This type does nothing when using Copy-On-Write strings. + struct __xfer_bufptrs + { + __xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { } + }; +#endif + + // The move constructor initializes an __xfer_bufptrs temporary then + // delegates to this constructor to performs moves during its lifetime. + basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&) + : __streambuf_type(static_cast(__rhs)), + _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string)) + { } +#endif };