aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-05-10 12:07:06 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-05-10 12:07:06 +0000
commitf8f49fd901bbcf7918756de217934be04aa08ab2 (patch)
treeb6dd1e6efe30ea9001e5e0f6fbdc4d32e1176ef4 /library/cpp
parentbaf1bdf7cd63c66eb710caafc3744c623592af1c (diff)
parent8173b4515355158a5787dcb12aa6036874776101 (diff)
downloadydb-f8f49fd901bbcf7918756de217934be04aa08ab2.tar.gz
Merge branch 'rightlib' into mergelibs-240510-1206
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/monlib/service/pages/templates.cpp1
-rw-r--r--library/cpp/monlib/service/pages/templates.h2
-rw-r--r--library/cpp/yt/memory/erased_storage-inl.h42
-rw-r--r--library/cpp/yt/memory/erased_storage.h61
-rw-r--r--library/cpp/yt/memory/unittests/erased_storage_ut.cpp130
-rw-r--r--library/cpp/yt/memory/unittests/ya.make3
-rw-r--r--library/cpp/yt/misc/concepts.h16
-rw-r--r--library/cpp/yt/misc/port.h4
8 files changed, 257 insertions, 2 deletions
diff --git a/library/cpp/monlib/service/pages/templates.cpp b/library/cpp/monlib/service/pages/templates.cpp
index ece12bea710..6a6aff37d13 100644
--- a/library/cpp/monlib/service/pages/templates.cpp
+++ b/library/cpp/monlib/service/pages/templates.cpp
@@ -31,5 +31,6 @@ namespace NMonitoring {
extern const char DListTag[] = "dl";
extern const char DTermTag[] = "dt";
extern const char DDescTag[] = "dd";
+ extern const char InputTag[] = "input";
}
diff --git a/library/cpp/monlib/service/pages/templates.h b/library/cpp/monlib/service/pages/templates.h
index 6cdcd6525c7..3a0b80684d9 100644
--- a/library/cpp/monlib/service/pages/templates.h
+++ b/library/cpp/monlib/service/pages/templates.h
@@ -220,6 +220,7 @@ namespace NMonitoring {
extern const char DListTag[3];
extern const char DTermTag[3];
extern const char DDescTag[3];
+ extern const char InputTag[6];
typedef TTag<HtmlTag> THtml;
typedef TTag<HeadTag> THead;
@@ -251,4 +252,5 @@ namespace NMonitoring {
typedef TTag<DListTag> DLIST;
typedef TTag<DTermTag> DTERM;
typedef TTag<DDescTag> DDESC;
+ typedef TTag<InputTag> TInput;
}
diff --git a/library/cpp/yt/memory/erased_storage-inl.h b/library/cpp/yt/memory/erased_storage-inl.h
new file mode 100644
index 00000000000..e4dc148e11e
--- /dev/null
+++ b/library/cpp/yt/memory/erased_storage-inl.h
@@ -0,0 +1,42 @@
+#ifndef ERASED_STORAGE_INL_H_
+#error "Direct inclusion of this file is not allowed, include erased_storage.h"
+// For the sake of sane code completion.
+#include "erased_storage.h"
+#endif
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <CTriviallyErasable TDecayedConcrete>
+TErasedStorage::TErasedStorage(TDecayedConcrete concrete) noexcept
+{
+ std::construct_at(
+ &AsConcrete<TDecayedConcrete>(),
+ concrete);
+}
+
+template <CTriviallyErasable TDecayedConcrete>
+TDecayedConcrete& TErasedStorage::AsConcrete() & noexcept
+{
+ using TPtr = TDecayedConcrete*;
+ return *std::launder(reinterpret_cast<TPtr>(&Bytes_));
+}
+
+template <CTriviallyErasable TDecayedConcrete>
+const TDecayedConcrete& TErasedStorage::AsConcrete() const & noexcept
+{
+ using TPtr = const TDecayedConcrete*;
+ return *std::launder(reinterpret_cast<TPtr>(&Bytes_));
+}
+
+template <CTriviallyErasable TDecayedConcrete>
+TDecayedConcrete&& TErasedStorage::AsConcrete() && noexcept
+{
+ using TPtr = TDecayedConcrete*;
+ return std::move(*std::launder(reinterpret_cast<TPtr>(&Bytes_)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/library/cpp/yt/memory/erased_storage.h b/library/cpp/yt/memory/erased_storage.h
new file mode 100644
index 00000000000..8e85430d0ba
--- /dev/null
+++ b/library/cpp/yt/memory/erased_storage.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <concepts>
+#include <memory>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+constexpr size_t ErasedStorageMaxByteSize = 32;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class TErasedStorage;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+concept CTriviallyErasable =
+ std::default_initializable<T> &&
+ std::is_trivially_destructible_v<T> &&
+ std::is_trivially_copyable_v<T> &&
+ (sizeof(T) <= ErasedStorageMaxByteSize) &&
+ (alignof(T) <= ErasedStorageMaxByteSize) &&
+ !std::is_reference_v<T> &&
+ !std::same_as<T, TErasedStorage>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+// This class does not call dtor of erased object
+// thus we require trivial destructability.
+class TErasedStorage
+{
+public:
+ template <CTriviallyErasable TDecayedConcrete>
+ explicit TErasedStorage(TDecayedConcrete concrete) noexcept;
+
+ TErasedStorage(const TErasedStorage& other) = default;
+ TErasedStorage& operator=(const TErasedStorage& other) = default;
+
+ template <CTriviallyErasable TDecayedConcrete>
+ TDecayedConcrete& AsConcrete() & noexcept;
+
+ template <CTriviallyErasable TDecayedConcrete>
+ const TDecayedConcrete& AsConcrete() const & noexcept;
+
+ template <CTriviallyErasable TDecayedConcrete>
+ TDecayedConcrete&& AsConcrete() && noexcept;
+
+private:
+ // NB(arkady-e1ppa): aligned_storage is deprecated.
+ alignas(ErasedStorageMaxByteSize) std::byte Bytes_[ErasedStorageMaxByteSize];
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define ERASED_STORAGE_INL_H_
+#include "erased_storage-inl.h"
+#undef ERASED_STORAGE_INL_H_
diff --git a/library/cpp/yt/memory/unittests/erased_storage_ut.cpp b/library/cpp/yt/memory/unittests/erased_storage_ut.cpp
new file mode 100644
index 00000000000..194c8e7fce5
--- /dev/null
+++ b/library/cpp/yt/memory/unittests/erased_storage_ut.cpp
@@ -0,0 +1,130 @@
+#include <library/cpp/testing/gtest/gtest.h>
+
+#include <library/cpp/yt/memory/erased_storage.h>
+
+#include <library/cpp/int128/int128.h>
+
+#include <library/cpp/yt/misc/guid.h>
+
+#include <util/generic/string.h>
+#include <util/system/types.h>
+
+#include <vector>
+
+namespace NYT {
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct TWithFieldInitalizer
+{
+ // NB: This class is not trivially default constructible.
+ int Field{};
+};
+
+static_assert(!std::is_trivially_default_constructible_v<TWithFieldInitalizer>);
+
+struct TCopyWithSideEffects
+{
+ TCopyWithSideEffects(const TCopyWithSideEffects&)
+ { }
+};
+
+static_assert(!std::is_trivially_copy_constructible_v<TCopyWithSideEffects>);
+
+struct TWithSubStruct
+{
+ TWithFieldInitalizer Field;
+};
+
+class TWithPrivateMembers
+{
+public:
+ TWithPrivateMembers() = default;
+
+private:
+ [[maybe_unused]] std::array<std::byte, 8> Data_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+TEST(TErasedStorageTest, Types)
+{
+ static_assert(CTriviallyErasable<int>);
+ static_assert(CTriviallyErasable<i32>);
+ static_assert(CTriviallyErasable<i64>);
+ static_assert(CTriviallyErasable<i128>);
+ static_assert(CTriviallyErasable<std::array<i128, 2>>);
+ static_assert(CTriviallyErasable<TGuid>);
+ static_assert(CTriviallyErasable<void*>);
+ static_assert(CTriviallyErasable<double>);
+ static_assert(CTriviallyErasable<const char*>);
+ static_assert(CTriviallyErasable<TWithFieldInitalizer>);
+ static_assert(CTriviallyErasable<TWithSubStruct>);
+ static_assert(CTriviallyErasable<TWithPrivateMembers>);
+ static_assert(CTriviallyErasable<char[8]>);
+
+ static_assert(!CTriviallyErasable<TString>);
+ static_assert(!CTriviallyErasable<std::vector<int>>);
+ static_assert(!CTriviallyErasable<std::array<i128, 3>>);
+ static_assert(!CTriviallyErasable<int&>);
+ static_assert(!CTriviallyErasable<const int&>);
+ static_assert(!CTriviallyErasable<int&&>);
+ static_assert(!CTriviallyErasable<TCopyWithSideEffects>);
+}
+
+TEST(TErasedStorageTest, JustWorks)
+{
+ int var = 42;
+
+ TErasedStorage stor(var);
+ EXPECT_EQ(stor.AsConcrete<int>(), 42);
+
+ var = 66;
+ EXPECT_EQ(stor.AsConcrete<int>(), 42);
+}
+
+TEST(TErasedStorageTest, CopyAssign)
+{
+ int var = 42;
+ TErasedStorage stor(var);
+ EXPECT_EQ(stor.AsConcrete<int>(), 42);
+
+ {
+ int anotherVar = 77;
+ stor = TErasedStorage(anotherVar);
+ }
+ EXPECT_EQ(stor.AsConcrete<int>(), 77);
+
+ double thirdVar = 9.92145214;
+ stor = TErasedStorage(thirdVar);
+ EXPECT_DOUBLE_EQ(stor.AsConcrete<double>(), 9.92145214);
+}
+
+TEST(TErasedStorageTest, Pointer)
+{
+ TString message("Hello world");
+ TErasedStorage stor(&message);
+
+ EXPECT_EQ(*stor.AsConcrete<TString*>(), TString("Hello world"));
+ message = "Goodbye world";
+
+ EXPECT_EQ(*stor.AsConcrete<TString*>(), "Goodbye world");
+}
+
+TEST(TErasedStorageTest, MutateStorage)
+{
+ int var = 0;
+ TErasedStorage stor(var);
+ EXPECT_EQ(stor.AsConcrete<int>(), 0);
+
+ auto& ref = stor.AsConcrete<int>();
+ ref = 88;
+
+ EXPECT_EQ(stor.AsConcrete<int>(), 88);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace
+} // namespace NYT
diff --git a/library/cpp/yt/memory/unittests/ya.make b/library/cpp/yt/memory/unittests/ya.make
index 4c3e4d53030..d2f098fa722 100644
--- a/library/cpp/yt/memory/unittests/ya.make
+++ b/library/cpp/yt/memory/unittests/ya.make
@@ -11,6 +11,7 @@ SRCS(
chunked_memory_pool_ut.cpp
chunked_memory_pool_allocator_ut.cpp
chunked_memory_pool_output_ut.cpp
+ erased_storage_ut.cpp
free_list_ut.cpp
function_view_ut.cpp
intrusive_ptr_ut.cpp
@@ -27,6 +28,8 @@ ENDIF()
PEERDIR(
library/cpp/testing/gtest
+ library/cpp/int128
+ library/cpp/yt/misc
library/cpp/yt/memory
)
diff --git a/library/cpp/yt/misc/concepts.h b/library/cpp/yt/misc/concepts.h
index 976c707ffec..5b84bac9059 100644
--- a/library/cpp/yt/misc/concepts.h
+++ b/library/cpp/yt/misc/concepts.h
@@ -1,6 +1,7 @@
#pragma once
#include <concepts>
+#include <vector>
namespace NYT {
@@ -46,4 +47,19 @@ concept CInvocable = NDetail::TIsInvocable<T, TSignature>::Value;
////////////////////////////////////////////////////////////////////////////////
+template <class V>
+concept CStdVector = requires (V& vec) {
+ [] <class... T> (std::vector<T...>&) { } (vec);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class M>
+concept CAnyMap = requires {
+ typename M::mapped_type;
+ typename M::key_type;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NYT
diff --git a/library/cpp/yt/misc/port.h b/library/cpp/yt/misc/port.h
index e30e163a59f..fe1c5e96de9 100644
--- a/library/cpp/yt/misc/port.h
+++ b/library/cpp/yt/misc/port.h
@@ -71,7 +71,7 @@
#endif
#if defined(_unix_)
- #define NO_UNIQUE_ADDRESS [[no_unique_address]]
+ #define YT_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
- #define NO_UNIQUE_ADDRESS
+ #define YT_ATTRIBUTE_NO_UNIQUE_ADDRESS
#endif