From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 0BE293881D04 for ; Thu, 16 Feb 2023 14:40:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0BE293881D04 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1676558418; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SDXX5XgJP2ZASaYhZSFJciG5OBZJm0blnOUsTQ3IxS8=; b=Lqda8H0utPegWEfY15OgwC7GI8HhLNRSKVnPTmmst9E6TdUm4ibSIWLGcGkPdKOVVClpJu DFdTyXlgFjWzVAHliioeilXEFovHuOSwGjRCcUucK/j5Vuciy/BIZyrFjiiQP+xoGP7LcR xf5fX6r4mFFTWCMsON+wu90ixtrC+3w= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-401-ThoklXJwMG6eB2kGmhQEog-1; Thu, 16 Feb 2023 09:40:17 -0500 X-MC-Unique: ThoklXJwMG6eB2kGmhQEog-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 10AC31C05ACA; Thu, 16 Feb 2023 14:40:17 +0000 (UTC) Received: from localhost (unknown [10.33.37.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id CD1FD40CF8E4; Thu, 16 Feb 2023 14:40:16 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Implement (P0290) Date: Thu, 16 Feb 2023 14:40:16 +0000 Message-Id: <20230216144016.138203-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested x86_64-linux. Pushed to trunk. -- >8 -- This was approved for the Concurrency TS v2 in Issaquah. Although the TS is based on C++20, this enables the new header for C++17 as well. This will make it available to more users, and I hope that will get more feedback on the feature. libstdc++-v3/ChangeLog: * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/experimental/synchronized_value: New file. * testsuite/experimental/synchronized_value.cc: New test. --- libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + .../include/experimental/synchronized_value | 100 ++++++++++++++++++ .../experimental/synchronized_value.cc | 42 ++++++++ 4 files changed, 144 insertions(+) create mode 100644 libstdc++-v3/include/experimental/synchronized_value create mode 100644 libstdc++-v3/testsuite/experimental/synchronized_value.cc diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 5b501272830..a880e8ee227 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -798,6 +798,7 @@ experimental_headers = \ ${experimental_srcdir}/source_location \ ${experimental_srcdir}/string \ ${experimental_srcdir}/string_view \ + ${experimental_srcdir}/synchronized_value \ ${experimental_srcdir}/system_error \ ${experimental_srcdir}/timer \ ${experimental_srcdir}/tuple \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 36e35e13806..0ff875b280b 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -1144,6 +1144,7 @@ experimental_headers = \ ${experimental_srcdir}/source_location \ ${experimental_srcdir}/string \ ${experimental_srcdir}/string_view \ + ${experimental_srcdir}/synchronized_value \ ${experimental_srcdir}/system_error \ ${experimental_srcdir}/timer \ ${experimental_srcdir}/tuple \ diff --git a/libstdc++-v3/include/experimental/synchronized_value b/libstdc++-v3/include/experimental/synchronized_value new file mode 100644 index 00000000000..9a91da912ca --- /dev/null +++ b/libstdc++-v3/include/experimental/synchronized_value @@ -0,0 +1,100 @@ +// -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/experimental/synchronized_value + * This is a TS C++ Library header. + * @ingroup libfund-ts + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_SYNCVAL +#define _GLIBCXX_EXPERIMENTAL_SYNCVAL 1 + +#pragma GCC system_header + +#include // for std::mutex + +#if __cplusplus >= 201703L +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace experimental::inline concurrency_v2 +{ +#define __cpp_lib_concurrency_v2_synchronized_value 202302 + + template + class synchronized_value + { + // TODO: Use partial specialization after PR c++/71954 is fixed. + template + static inline constexpr bool __is_self + = sizeof...(_Args) == 1 + && (is_same_v<__remove_cvref_t<_Args>, synchronized_value> && ...); + +#if ! __cpp_concepts + template + using __not_self = bool_constant>; +#endif + + public: + synchronized_value(const synchronized_value&) = delete; + synchronized_value& operator=(const synchronized_value&) = delete; + +#if __cpp_concepts + template + requires (!__is_self<_Args...>) && is_constructible_v<_Tp, _Args...> +#else + template>, + typename = _Require>> +#endif + synchronized_value(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : _M_val(std::forward<_Args>(__args)...) + { } + + template + friend invoke_result_t<_Fn, _Up&, _Types&...> + apply(_Fn&&, synchronized_value<_Up>&, synchronized_value<_Types>&...); + + private: + mutex _M_mut; + _Tp _M_val; + }; + + template + inline invoke_result_t<_Fn, _Tp&, _Types&...> + apply(_Fn&& __f, synchronized_value<_Tp>& __val, + synchronized_value<_Types>&... __vals) + { + scoped_lock __l(__val._M_mut, __vals._M_mut...); + return std::__invoke(std::forward<_Fn>(__f), __val._M_val, + __vals._M_val...); + } +} // namespace experimental::concurrency_v2 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _GLIBCXX_EXPERIMENTAL_SYNCVAL diff --git a/libstdc++-v3/testsuite/experimental/synchronized_value.cc b/libstdc++-v3/testsuite/experimental/synchronized_value.cc new file mode 100644 index 00000000000..8e8134699a2 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/synchronized_value.cc @@ -0,0 +1,42 @@ +// { dg-do run { target c++17 } } + +#include +#include +#include + +using std::experimental::synchronized_value; + +synchronized_value s; + +std::string read_value(){ + return apply([](auto& x){return x;},s); +} + +void set_value(std::string const& new_val){ + apply([&](auto& x){ x = new_val; }, s); +} + +void +test_single() +{ + set_value("new value"); + VERIFY( read_value() == "new value" ); +} + +void +test_multi() +{ + synchronized_value a(1), b(2), c(3); + int sum = apply([](auto&... ints) { return (ints++ + ...); }, a, b, c); + VERIFY( sum == 6 ); + auto get = [](int& i) { return i; }; + VERIFY( apply(get, a) == 2 ); + VERIFY( apply(get, b) == 3 ); + VERIFY( apply(get, c) == 4 ); +} + +int main() +{ + test_single(); + test_multi(); +} -- 2.39.2