diff options
author | Alexander Smirnov <alex@ydb.tech> | 2024-05-10 12:07:06 +0000 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2024-05-10 12:07:06 +0000 |
commit | f8f49fd901bbcf7918756de217934be04aa08ab2 (patch) | |
tree | b6dd1e6efe30ea9001e5e0f6fbdc4d32e1176ef4 /library/cpp | |
parent | baf1bdf7cd63c66eb710caafc3744c623592af1c (diff) | |
parent | 8173b4515355158a5787dcb12aa6036874776101 (diff) | |
download | ydb-f8f49fd901bbcf7918756de217934be04aa08ab2.tar.gz |
Merge branch 'rightlib' into mergelibs-240510-1206
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/monlib/service/pages/templates.cpp | 1 | ||||
-rw-r--r-- | library/cpp/monlib/service/pages/templates.h | 2 | ||||
-rw-r--r-- | library/cpp/yt/memory/erased_storage-inl.h | 42 | ||||
-rw-r--r-- | library/cpp/yt/memory/erased_storage.h | 61 | ||||
-rw-r--r-- | library/cpp/yt/memory/unittests/erased_storage_ut.cpp | 130 | ||||
-rw-r--r-- | library/cpp/yt/memory/unittests/ya.make | 3 | ||||
-rw-r--r-- | library/cpp/yt/misc/concepts.h | 16 | ||||
-rw-r--r-- | library/cpp/yt/misc/port.h | 4 |
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 |