-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc++] Adds shared resource helper. #72529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
3584476
to
82616ca
Compare
This is based on the __wrapped_streambuf_mutex class used in <syncstream>. This is a generic version set to replace __wrapped_streambuf_mutex.
82616ca
to
e95f97e
Compare
@llvm/pr-subscribers-libcxx Author: Mark de Wever (mordante) ChangesThis is based on the __wrapped_streambuf_mutex class used in <syncstream>. This is a generic version set to replace __wrapped_streambuf_mutex. Patch is 22.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/72529.diff 15 Files Affected:
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 889d7fedbf2965f..75d47979645c7bd 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -854,6 +854,7 @@ set(files
__utility/piecewise_construct.h
__utility/priority_tag.h
__utility/rel_ops.h
+ __utility/shared_resource.h
__utility/small_buffer.h
__utility/swap.h
__utility/to_underlying.h
diff --git a/libcxx/include/__availability b/libcxx/include/__availability
index 99a16c968de3c60..c76faf5eefce9f3 100644
--- a/libcxx/include/__availability
+++ b/libcxx/include/__availability
@@ -139,6 +139,12 @@
// # define _LIBCPP_AVAILABILITY_HAS_NO_TZDB
# define _LIBCPP_AVAILABILITY_TZDB
+ // This controls the availability of the shared resource code.
+ // This is used in syncstream to synchronize write operations,
+ // but the code is generic and can be used for similar purposes.
+// # define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_RESOURCE
+# define _LIBCPP_AVAILABILITY_SHARED_RESOURCE
+
// Enable additional explicit instantiations of iostreams components. This
// reduces the number of weak definitions generated in programs that use
// iostreams by providing a single strong definition in the shared library.
@@ -241,6 +247,9 @@
# define _LIBCPP_AVAILABILITY_HAS_NO_TZDB
# define _LIBCPP_AVAILABILITY_TZDB __attribute__((unavailable))
+# define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_RESOURCE
+# define _LIBCPP_AVAILABILITY_SHARED_RESOURCE __attribute__((unavailable))
+
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 120000) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 150000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 150000) || \
diff --git a/libcxx/include/__utility/shared_resource.h b/libcxx/include/__utility/shared_resource.h
new file mode 100644
index 000000000000000..ee5182007a9c65f
--- /dev/null
+++ b/libcxx/include/__utility/shared_resource.h
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_SHARED_RESOURCE_H
+#define _LIBCPP___UTILITY_SHARED_RESOURCE_H
+
+#include <__availability>
+#include <__config>
+#include <__mutex/lock_guard.h>
+#include <__mutex/mutex.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#ifndef _LIBCPP_HAS_NO_THREADS
+
+// Contains helper functions for a reference counted resource.
+// The resources are identified by their address. The reference counting is
+// done by calling increasing and decreasing the reference count at the
+// appropriate time.
+//
+// There are two ways to guard the resource against concurrent access:
+// - Call the lock function. The function locks two mutexes
+// - The internal map's mutex
+// - The mutex of the resource
+// This approach does not require to store a pointer/reference to the mutex,
+// reducing the size of the object.
+// - Store the mutex of the inc function. Then the caller can lock the mutex at
+// the appropriate time.
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// std::mutex is available as an extension since C++03, but returning a
+// lock_guard requires C++17. Since the current use-cases require newer C++
+// versions the older versions are not supported.
+# if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_RESOURCE mutex&
+__shared_resource_inc_reference(const void* __ptr);
+
+// precondition: __ptr's reference count > 0
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_RESOURCE void __shared_resource_dec_reference(const void* __ptr);
+
+// precondition: __ptr's reference count > 0
+[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_RESOURCE lock_guard<mutex>
+__shared_resource_get_lock(const void* __ptr);
+
+# endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_NO_THREADS
+#endif // _LIBCPP___UTILITY_SHARED_RESOURCE_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 17ebe48f329963d..607caea93ce2f23 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2084,6 +2084,7 @@ module std_private_utility_piecewise_construct [system] { header "__utility/p
module std_private_utility_priority_tag [system] { header "__utility/priority_tag.h" }
module std_private_utility_rel_ops [system] { header "__utility/rel_ops.h" }
module std_private_utility_small_buffer [system] { header "__utility/small_buffer.h" }
+module std_private_utility_shared_resource [system] { header "__utility/shared_resource.h" }
module std_private_utility_swap [system] {
header "__utility/swap.h"
export std_private_type_traits_is_swappable
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 8daad89f52e6f7c..76db0097233ea6a 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1534,7 +1534,10 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__126__shared_resource_get_lockEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__131__shared_resource_dec_referenceEPKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__131__shared_resource_inc_referenceEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__13cinE', 'size': 0, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 91976f500539daa..4d9f7f690e06727 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -568,7 +568,10 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__126__shared_resource_get_lockEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__shared_resource_dec_referenceEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__shared_resource_inc_referenceEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__134__construct_barrier_algorithm_baseERl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__13cinE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 8a98d42a2a1aa02..1f866c69468047d 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -568,7 +568,10 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIlNS_22__cxx_atomic_base_implIlEEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__126__shared_resource_get_lockEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__shared_resource_dec_referenceEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__shared_resource_inc_referenceEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__134__construct_barrier_algorithm_baseERl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__13cinE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 0c06b5097b83f80..cdad4ccc69cdbd9 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1534,7 +1534,10 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__126__shared_resource_get_lockEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__131__shared_resource_dec_referenceEPKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__131__shared_resource_inc_referenceEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__13cinE', 'size': 0, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index 16658fdff54932b..58566be937c1f3e 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1229,7 +1229,10 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIlNS_22__cxx_atomic_base_implIlEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__126__shared_resource_get_lockEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_dec_referenceEPKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_inc_referenceEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__13cinE', 'size': 168, 'type': 'OBJECT'}
@@ -2025,4 +2028,4 @@
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD0Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'}
\ No newline at end of file
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 49e3579614ee8c1..0e6661dbb6df9bb 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1227,7 +1227,10 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__126__shared_resource_get_lockEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_dec_referenceEPKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_inc_referenceEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__13cinE', 'size': 168, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 764e7c37daacb7c..869b96bfcea1d94 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -1199,7 +1199,10 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__126__shared_resource_get_lockEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_dec_referenceEPKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__131__shared_resource_inc_referenceEPKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__13cinE', 'size': 168, 'type': 'OBJECT'}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 156dbe8a4c2f92e..c9671d76e48380c 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -72,6 +72,7 @@ if (LIBCXX_ENABLE_THREADS)
mutex_destructor.cpp
mutex.cpp
shared_mutex.cpp
+ shared_resource.cpp
thread.cpp
)
endif()
diff --git a/libcxx/src/shared_resource.cpp b/libcxx/src/shared_resource.cpp
new file mode 100644
index 000000000000000..6c4fb442a2c1c82
--- /dev/null
+++ b/libcxx/src/shared_resource.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+#include <mutex>
+#include <shared_mutex>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+class __shared_resource {
+public:
+ _LIBCPP_HIDE_FROM_ABI __shared_resource() = default;
+ __shared_resource(const __shared_resource&) = delete;
+ __shared_resource& operator=(const __shared_resource&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI mutex& __inc_reference(const void* __ptr) {
+ _LIBCPP_ASSERT_NON_NULL(__ptr != nullptr, "not a valid resource");
+ unique_lock __lock{__mutex_};
+
+ auto& __resource = __lut_[reinterpret_cast<uintptr_t>(__ptr)];
+ ++__resource.__count;
+ return __resource.__mutex;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI void __dec_reference(const void* __ptr) {
+ unique_lock __lock{__mutex_};
+
+ auto __it = __get_it(__ptr);
+ if (__it->second.__count == 1)
+ __lut_.erase(__it);
+ else
+ --__it->second.__count;
+ }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI lock_guard<mutex> __get_lock(const void* __ptr) {
+ shared_lock __lock{__mutex_};
+ return lock_guard{__get_it(__ptr)->second.__mutex};
+ }
+
+ [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI __shared_resource& __instance() {
+ static __shared_resource __result;
+ return __result;
+ }
+
+private:
+ struct __value {
+ mutex __mutex;
+ size_t __count{0};
+ };
+
+ shared_mutex __mutex_;
+ map<uintptr_t, __value> __lut_;
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI map<uintptr_t, __value>::iterator __get_it(const void* __ptr) {
+ _LIBCPP_ASSERT_NON_NULL(__ptr != nullptr, "not a valid resource");
+
+ auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr));
+ _LIBCPP_ASSERT_INTERNAL(__it != __lut_.end(), "the resource is not registered");
+ _LIBCPP_ASSERT_INTERNAL(__it->second.__count > 0, "the resouce is not active");
+ return __it;
+ }
+};
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_RESOURCE mutex&
+__shared_resource_inc_reference(const void* __ptr) {
+ return __shared_resource::__instance().__inc_reference(__ptr);
+}
+
+_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_RESOURCE void __shared_resource_dec_reference(const void* __ptr) {
+ _...
[truncated]
|
// This controls the availability of the shared resource code. | ||
// This is used in syncstream to synchronize write operations, | ||
// but the code is generic and can be used for similar purposes. | ||
// # define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_RESOURCE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be adjusted on top of main
.
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} | ||
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD0Ev', 'type': 'FUNC'} | ||
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'} | ||
{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's just add a newline to remove this diff.
Feature( | ||
name="availability-shared_resource-missing", | ||
when=lambda cfg: BooleanExpression.evaluate( | ||
# TODO(ldionne) Please provide the correct value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# TODO(ldionne) Please provide the correct value. | |
# TODO(ldionne): Update once this has shipped. |
std::lock_guard b_lock{b_mutex}; | ||
std::lock_guard c_lock = std::__shared_resource_get_lock(&c); | ||
} | ||
{ // Test the lock of a locks the mutex returned by inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ // Test the lock of a locks the mutex returned by inc. | |
{ // Test that the lock is really associated to the given address. |
size_t __count{0}; | ||
}; | ||
|
||
shared_mutex __mutex_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename this to something like __map_mutex_
since it's really intended to guard the std::map
access.
}; | ||
|
||
shared_mutex __mutex_; | ||
map<uintptr_t, __value> __lut_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
map
is rarely the best way of storing data. I would suggest either using unordered_map
or implementing a simple hash table for internal use only. Maybe unordered_map
is easiest for now, especially since we can change it however we want since it's just in the dylib.
} | ||
|
||
private: | ||
struct __value { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are many similarities with what we do in stop_token
here. This is basically a ref-counted mutex, and that's very close to what we do with __intrusive_shared_ptr
and __atomic_unique_lock
in the stop_token
implementation. I wonder whether it would make sense to reuse some of that work here. In particular, we know for sure that std::map
+ std::mutex
is probably not the best way of implementing the storage for this, so perhaps we can do something clever by using a slightly different data structure.
I'd be curious if you have thoughts about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huixie90 Do you have thoughts on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huixie90 Friendly ping.
I would like a day or two to look over this. |
This abstraction is scary & heavy weight. Why do we need a generic version of it? I wouldn't be comfortable proceeding with this change until I understand where and how it's going to be used, and I see it used in real code. I'm very uncomfortable adding utility code without users. I don't need this change to contain the changes which use it, but I would like to see it before this proceeds. |
This is to refactor |
@ldionne FYI I discussed this offline with @EricWF last week. |
This is based on the __wrapped_streambuf_mutex class used in
<syncstream>
. This is a generic version set to replace __wrapped_streambuf_mutex.