aboutsummaryrefslogtreecommitdiffstats
path: root/library
diff options
context:
space:
mode:
authorinnokentii <innokentii@yandex-team.com>2022-12-07 22:57:04 +0300
committerinnokentii <innokentii@yandex-team.com>2022-12-07 22:57:04 +0300
commit613dcecbea7f8bd6c041c2caef1c8b85640a0760 (patch)
tree815dcaeafd6a387700765e72890827688b4dccf7 /library
parent026646ec03982a24cd4b0488c94094b1ead8ce10 (diff)
downloadydb-613dcecbea7f8bd6c041c2caef1c8b85640a0760.tar.gz
TContiguousData reimplement backend
replace shared_data controlling backend with internal one
Diffstat (limited to 'library')
-rw-r--r--library/cpp/actors/util/CMakeLists.txt1
-rw-r--r--library/cpp/actors/util/contiguous_data.cpp50
-rw-r--r--library/cpp/actors/util/contiguous_data.h172
-rw-r--r--library/cpp/actors/util/contiguous_data_backend.h230
-rw-r--r--library/cpp/actors/util/contiguous_data_ut.cpp20
-rw-r--r--library/cpp/neh/http2.cpp4
6 files changed, 276 insertions, 201 deletions
diff --git a/library/cpp/actors/util/CMakeLists.txt b/library/cpp/actors/util/CMakeLists.txt
index 96eee91c9e..19f683cb2a 100644
--- a/library/cpp/actors/util/CMakeLists.txt
+++ b/library/cpp/actors/util/CMakeLists.txt
@@ -18,7 +18,6 @@ target_sources(cpp-actors-util PRIVATE
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/affinity.cpp
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_track.cpp
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/contiguous_data.cpp
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data.cpp
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/should_continue.cpp
${CMAKE_SOURCE_DIR}/library/cpp/actors/util/threadparkpad.cpp
diff --git a/library/cpp/actors/util/contiguous_data.cpp b/library/cpp/actors/util/contiguous_data.cpp
deleted file mode 100644
index 8a9cb6ef1a..0000000000
--- a/library/cpp/actors/util/contiguous_data.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "contiguous_data.h"
-
-size_t checkedSum(size_t a, size_t b) {
- if (a > std::numeric_limits<size_t>::max() - b) {
- throw std::length_error("Allocate size overflow");
- }
- return a + b;
-}
-
-char* TContiguousData::TBackend::TSharedDataControllingOwner::Allocate(size_t size, size_t headroom, size_t tailroom) {
- char* data = nullptr;
-
- size_t fullSize = checkedSum(size, checkedSum(headroom, tailroom));
-
- if (fullSize > 0) {
- auto allocSize = checkedSum(fullSize, OverheadSize);
- char* raw = static_cast<char*>(y_allocate(allocSize));
-
- auto isAligned = [](const void * ptr, std::uintptr_t alignment) noexcept {
- auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
- return !(iptr % alignment);
- };
- Y_VERIFY(isAligned(raw, alignof(TBackend::TCookies)));
- TBackend::TCookies* cookies = new(raw) TBackend::TCookies();
-
- auto* header = reinterpret_cast<NActors::TSharedData::THeader*>(raw + PrivateHeaderSize);
- header->RefCount = 1;
- header->Owner = &TContiguousData::TBackend::SharedDataOwner;
-
- data = raw + OverheadSize;
- cookies->Begin = data + headroom;
- cookies->End = data + headroom + size;
- }
- return data;
-}
-
-bool TContiguousData::TBackend::TSharedDataControllingOwner::CheckControlled(const char *data) noexcept {
- if (data != nullptr) {
- auto* header = reinterpret_cast<const NActors::TSharedData::THeader*>(data - HeaderSize);
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- // WARNING: with this definition method should be called ONLY on instances
- // which passed through TBackTracingOwner::FakeOwner
- const TBackTracingOwner* owner = reinterpret_cast<const TBackTracingOwner*>(header->Owner);
- return owner->GetRealOwner() == &TContiguousData::TBackend::SharedDataOwner;
-#else
- return header->Owner == &TContiguousData::TBackend::SharedDataOwner;
-#endif
- }
- return false;
-}
diff --git a/library/cpp/actors/util/contiguous_data.h b/library/cpp/actors/util/contiguous_data.h
index 35f9d25b33..22b28d3c46 100644
--- a/library/cpp/actors/util/contiguous_data.h
+++ b/library/cpp/actors/util/contiguous_data.h
@@ -14,6 +14,7 @@
#include <util/system/sys_alloc.h>
#include "shared_data.h"
+#include "contiguous_data_backend.h"
#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
#include "shared_data_backtracing_owner.h"
@@ -291,12 +292,15 @@ class TRopeArena;
class TContiguousData {
friend class TRope;
friend class TRopeArena;
+
+ using TInternalBackend = NDetail::TContiguousDataInternalBackend;
+
class TBackend {
enum class EType : uintptr_t {
STRING,
SHARED_DATA,
- SHARED_DATA_CONTROLLED_BY_OWNER,
- ROPE_CHUNK_BACKEND,
+ INTERNAL_BACKEND,
+ EXTERNAL_BACKEND,
};
struct TBackendHolder {
@@ -312,62 +316,13 @@ class TContiguousData {
static_assert(sizeof(TBackendHolder) >= sizeof(TString));
#endif
static_assert(sizeof(TBackendHolder) >= sizeof(NActors::TSharedData));
+ static_assert(sizeof(TBackendHolder) >= sizeof(TInternalBackend));
TBackendHolder Owner = TBackend::Empty; // lower bits contain type of the owner
public:
- struct TCookies {
- using TSelf = TCookies;
- std::atomic<const char*> Begin;
- std::atomic<const char*> End;
-
- static size_t BytesToAligned(size_t size) {
- bool misaligned = size % alignof(TSelf);
- return misaligned ? alignof(TSelf) - size % alignof(TSelf) : 0;
- }
-
- static size_t BytesToAlloc(size_t size) {
- return size + BytesToAligned(size) + sizeof(TSelf);
- }
- };
-
- struct TSharedDataControllingOwner : public NActors::TSharedData::IOwner {
- enum : size_t {
- PrivateHeaderSize = sizeof(TCookies),
- HeaderSize = sizeof(NActors::TSharedData::THeader),
- OverheadSize = PrivateHeaderSize + HeaderSize,
- MaxDataSize = (std::numeric_limits<size_t>::max() - OverheadSize)
- };
-
- static char* Allocate(size_t size, size_t headroom = 0, size_t tailroom = 0);
-
- static TCookies* GetCookies(char* data) noexcept {
- if (data != nullptr) {
- return reinterpret_cast<TCookies*>(data - OverheadSize);
- }
- return nullptr;
- }
-
- static const TCookies* GetCookies(const char* data) noexcept {
- if (data != nullptr) {
- return reinterpret_cast<const TCookies*>(data - OverheadSize);
- }
- return nullptr;
- }
+ using TCookies = TInternalBackend::TCookies;
- static bool CheckControlled(const char* data) noexcept;
-
- void Deallocate(char* data) noexcept override {
- if (data) {
- char* raw = data - OverheadSize;
- TCookies* cookies = reinterpret_cast<TCookies*>(raw);
- cookies->~TCookies();
- y_deallocate(raw);
- }
- }
- };
-
- inline static TSharedDataControllingOwner SharedDataOwner {};
static constexpr struct TControlToken {} ControlToken;
static constexpr size_t CookiesSize = sizeof(TCookies);
@@ -386,12 +341,15 @@ class TContiguousData {
{}
TBackend(NActors::TSharedData s)
- : Owner(Construct<NActors::TSharedData>(
- TSharedDataControllingOwner::CheckControlled(s.data()) ? EType::SHARED_DATA_CONTROLLED_BY_OWNER : EType::SHARED_DATA, std::move(s)))
+ : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA, std::move(s)))
+ {}
+
+ TBackend(TInternalBackend backend)
+ : Owner(Construct<TInternalBackend>(EType::INTERNAL_BACKEND, std::move(backend)))
{}
TBackend(IContiguousChunk::TPtr backend)
- : Owner(Construct<IContiguousChunk::TPtr>(EType::ROPE_CHUNK_BACKEND, std::move(backend)))
+ : Owner(Construct<IContiguousChunk::TPtr>(EType::EXTERNAL_BACKEND, std::move(backend)))
{}
~TBackend() {
@@ -440,14 +398,10 @@ class TContiguousData {
if(!Owner) {
return nullptr;
}
- return Visit(Owner, [](EType type, auto& value) -> TCookies* {
+ return Visit(Owner, [](EType, auto& value) -> TCookies* {
using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED_BY_OWNER) {
- return TSharedDataControllingOwner::GetCookies(const_cast<char*>(value.data()));
- } else {
- return nullptr;
- }
+ if constexpr (std::is_same_v<T, TInternalBackend>) {
+ return value.GetCookies();
} else {
return nullptr;
}
@@ -464,7 +418,7 @@ class TContiguousData {
}
return Visit(Owner, [](EType, auto& value) -> bool {
using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ if constexpr (std::is_same_v<T, NActors::TSharedData> || std::is_same_v<T, TInternalBackend>) {
return value.IsPrivate();
} else {
return false;
@@ -480,7 +434,7 @@ class TContiguousData {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, TString>) {
return {&(*value.cbegin()), value.size()};
- } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData> || std::is_same_v<T, TInternalBackend>) {
return {value.data(), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->GetData();
@@ -503,6 +457,11 @@ class TContiguousData {
value = NActors::TSharedData::Copy(value.data(), value.size());
}
return {value.mutable_data(), value.size()};
+ } else if constexpr (std::is_same_v<T, TInternalBackend>) {
+ if (value.IsShared()) {
+ value = TInternalBackend::Copy(value.data(), value.size());
+ }
+ return {value.mutable_data(), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->GetDataMut();
} else {
@@ -519,7 +478,7 @@ class TContiguousData {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, TString>) {
return {const_cast<char*>(value.data()), value.size()};
- } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData> || std::is_same_v<T, TInternalBackend>) {
return {const_cast<char*>(value.data()), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->UnsafeGetDataMut();
@@ -537,7 +496,7 @@ class TContiguousData {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, TString>) {
return value.capacity();
- } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData> || std::is_same_v<T, TInternalBackend>) {
return value.size(); // There is no capacity
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->GetOccupiedMemorySize();
@@ -609,18 +568,6 @@ class TContiguousData {
return false;
}
- void Disown() {
- if (Owner) {
- const EType type = static_cast<EType>(Owner.Data[0] & TypeMask);
-
- if (type == EType::SHARED_DATA_CONTROLLED_BY_OWNER) {
- if (IsPrivate()) {
- Owner.Data[0] = (Owner.Data[0] & ValueMask) | static_cast<uintptr_t>(EType::SHARED_DATA);
- }
- }
- }
- }
-
template <class TResult>
TResult GetRaw() const {
if (!Owner) {
@@ -707,9 +654,9 @@ class TContiguousData {
};
switch (type) {
case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value));
- case EType::SHARED_DATA_CONTROLLED_BY_OWNER: [[fallthrough]];
case EType::SHARED_DATA: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const NActors::TSharedData&, NActors::TSharedData&>>(value));
- case EType::ROPE_CHUNK_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IContiguousChunk::TPtr&, IContiguousChunk::TPtr&>>(value));
+ case EType::INTERNAL_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TInternalBackend&, TInternalBackend&>>(value));
+ case EType::EXTERNAL_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IContiguousChunk::TPtr&, IContiguousChunk::TPtr&>>(value));
}
Y_FAIL("Unexpected type# %" PRIu64, static_cast<ui64>(type));
}
@@ -747,17 +694,23 @@ class TContiguousData {
const char *Begin; // data start
const char *End; // data end
- explicit TContiguousData(NActors::TSharedData s, const char *data, size_t size, TBackend::TControlToken)
+ explicit TContiguousData(TInternalBackend s, const char *data, size_t size)
: Backend(std::move(s))
{
- Y_VERIFY(s.data() == nullptr || TBackend::TSharedDataControllingOwner::CheckControlled(s.data()));
- Y_VERIFY(s.data() == nullptr ||
- (TBackend::TSharedDataControllingOwner::GetCookies(s.data())->Begin == data
- && TBackend::TSharedDataControllingOwner::GetCookies(s.data())->End == data + size));
+ Y_VERIFY(Backend.GetData().data() == nullptr ||
+ (Backend.GetCookies() && Backend.GetCookies()->Begin == data && Backend.GetCookies()->End == data + size));
Begin = data;
End = data + size;
}
+ explicit TContiguousData(TInternalBackend s)
+ : Backend(std::move(s))
+ {
+ auto span = Backend.GetData();
+ Begin = span.data();
+ End = Begin + span.size();
+ }
+
TContiguousData(TOwnedSlice, const char *data, size_t size, const TContiguousData& from)
: TContiguousData(from.Backend, {data, size})
{
@@ -798,29 +751,16 @@ public:
{}
explicit TContiguousData(TString s)
-#ifndef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
: Backend(std::move(s))
-#endif
{
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- auto ss = NActors::TSharedData::Copy(s.data(), s.size());
- TBackTracingOwner::FakeOwner(ss, TBackTracingOwner::INFO_COPIED_STRING);
- Backend = TBackend(std::move(ss));
-#endif
auto span = Backend.GetData();
Begin = span.data();
End = Begin + span.size();
}
explicit TContiguousData(NActors::TSharedData s)
-#ifndef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
: Backend(std::move(s))
-#endif
{
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- TBackTracingOwner::FakeOwner(s, TBackTracingOwner::INFO_FROM_SHARED_DATA);
- Backend = TBackend(std::move(s));
-#endif
auto span = Backend.GetData();
Begin = span.data();
End = Begin + span.size();
@@ -862,24 +802,18 @@ public:
if (size == 0) {
return TContiguousData();
}
+
if (headroom == 0 && tailroom == 0) {
- NActors::TSharedData res = NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size), size);
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINITIALIZED);
-#endif
+ TInternalBackend res = TInternalBackend::Uninitialized(size);
return TContiguousData(
OwnedSlice,
res.data(),
res.data() + res.size(),
TContiguousData(res));
- } else {
- auto fullSize = size + headroom + tailroom;
- NActors::TSharedData res = NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size, headroom, tailroom), fullSize);
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINIT_ROOMS);
-#endif
- return TContiguousData(res, res.data() + headroom, size, TBackend::ControlToken);
}
+
+ TInternalBackend res = TInternalBackend::Uninitialized(size, headroom, tailroom);
+ return TContiguousData(res, res.data() + headroom, size);
}
static TContiguousData Copy(TContiguousSpan data, size_t headroom = 0, size_t tailroom = 0) {
@@ -892,10 +826,6 @@ public:
return Copy({data, size}, headroom, tailroom);
}
- static NActors::TSharedData UninitializedSharedData(size_t size) {
- return NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size), size);
- }
-
template <class TType>
bool ContainsNativeType() const {
return Backend.ContainsNativeType<TType>();
@@ -1077,13 +1007,6 @@ public:
Begin -= size;
return EResizeResult::NoAlloc;
} else {
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- if (Backend.ContainsNativeType<NActors::TSharedData>()) {
- Cerr << "GrowFront# " << size;
- NActors::TSharedData data = GetRaw<NActors::TSharedData>();
- TBackTracingOwner::UnsafePrintBackTrace(data);
- }
-#endif
if (strategy == EResizeStrategy::FailOnCopy && static_cast<bool>(Backend)) {
Y_FAIL("Fail on grow");
}
@@ -1101,13 +1024,6 @@ public:
End += size;
return EResizeResult::NoAlloc;
} else {
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- if (Backend.ContainsNativeType<NActors::TSharedData>()) {
- Cerr << "GrowBack# " << size;
- NActors::TSharedData data = GetRaw<NActors::TSharedData>();
- TBackTracingOwner::UnsafePrintBackTrace(data);
- }
-#endif
if (strategy == EResizeStrategy::FailOnCopy && static_cast<bool>(Backend)) {
Y_FAIL("Fail on grow");
}
diff --git a/library/cpp/actors/util/contiguous_data_backend.h b/library/cpp/actors/util/contiguous_data_backend.h
new file mode 100644
index 0000000000..9f97906114
--- /dev/null
+++ b/library/cpp/actors/util/contiguous_data_backend.h
@@ -0,0 +1,230 @@
+#pragma once
+
+#include <atomic>
+
+#include <library/cpp/deprecated/atomic/atomic.h>
+
+#include <util/system/types.h>
+#include <util/system/compiler.h>
+#include <util/generic/array_ref.h>
+#include <util/system/sys_alloc.h>
+
+namespace NDetail {
+
+struct TContiguousDataInternalBackend {
+public:
+ struct TCookies {
+ using TSelf = TCookies;
+ std::atomic<const char*> Begin;
+ std::atomic<const char*> End;
+
+ static size_t BytesToAligned(size_t size) {
+ bool misaligned = size % alignof(TSelf);
+ return misaligned ? alignof(TSelf) - size % alignof(TSelf) : 0;
+ }
+
+ static size_t BytesToAlloc(size_t size) {
+ return size + BytesToAligned(size) + sizeof(TSelf);
+ }
+ };
+private:
+ // to be binary compatible with TSharedData
+ struct THeader : public TCookies {
+ TAtomic RefCount;
+ ui64 Zero = 0;
+ };
+
+ enum : size_t {
+ HeaderSize = sizeof(THeader),
+ OverheadSize = HeaderSize,
+ MaxDataSize = (std::numeric_limits<size_t>::max() - OverheadSize)
+ };
+
+public:
+ TContiguousDataInternalBackend() noexcept
+ : Data_(nullptr)
+ , Size_(0)
+ { }
+
+ ~TContiguousDataInternalBackend() noexcept {
+ Release();
+ }
+
+ TContiguousDataInternalBackend(const TContiguousDataInternalBackend& other) noexcept
+ : Data_(other.Data_)
+ , Size_(other.Size_)
+ {
+ AddRef();
+ }
+
+ TContiguousDataInternalBackend(TContiguousDataInternalBackend&& other) noexcept
+ : Data_(other.Data_)
+ , Size_(other.Size_)
+ {
+ other.Data_ = nullptr;
+ other.Size_ = 0;
+ }
+
+ TContiguousDataInternalBackend& operator=(const TContiguousDataInternalBackend& other) noexcept {
+ if (this != &other) {
+ Release();
+ Data_ = other.Data_;
+ Size_ = other.Size_;
+ AddRef();
+ }
+ return *this;
+ }
+
+ TContiguousDataInternalBackend& operator=(TContiguousDataInternalBackend&& other) noexcept {
+ if (this != &other) {
+ Release();
+ Data_ = other.Data_;
+ Size_ = other.Size_;
+ other.Data_ = nullptr;
+ other.Size_ = 0;
+ }
+ return *this;
+ }
+
+ Y_FORCE_INLINE explicit operator bool() const { return Size_ > 0; }
+
+ Y_FORCE_INLINE char* mutable_data() { return Data(); }
+ Y_FORCE_INLINE char* mutable_begin() { return Data(); }
+ Y_FORCE_INLINE char* mutable_end() { return Data() + Size_; }
+
+ Y_FORCE_INLINE const char* data() const { return Data(); }
+ Y_FORCE_INLINE const char* begin() const { return Data(); }
+ Y_FORCE_INLINE const char* end() const { return Data() + Size_; }
+
+ Y_FORCE_INLINE size_t size() const { return Size_; }
+
+ /**
+ * Copies data to new allocated buffer if data is shared
+ * New container loses original owner
+ * Returns pointer to mutable buffer
+ */
+ char* Detach() {
+ if (IsShared()) {
+ *this = TContiguousDataInternalBackend::Copy(data(), size());
+ }
+ return Data_;
+ }
+
+ bool IsPrivate() const {
+ return Data_ ? IsPrivate(Header()) : true;
+ }
+
+ bool IsShared() const {
+ return !IsPrivate();
+ }
+
+ TString ToString() const {
+ return TString(data(), size());
+ }
+
+ TCookies* GetCookies() {
+ return Header();
+ }
+
+ /**
+ * Attach to pre-allocated data with a preceding THeader
+ */
+ static TContiguousDataInternalBackend AttachUnsafe(char* data, size_t size) noexcept {
+ TContiguousDataInternalBackend result;
+ result.Data_ = data;
+ result.Size_ = size;
+ return result;
+ }
+
+ /**
+ * Make uninitialized buffer of the specified size
+ */
+ static TContiguousDataInternalBackend Uninitialized(size_t size, size_t headroom = 0, size_t tailroom = 0) {
+ size_t fullSize = checkedSum(size, checkedSum(headroom, tailroom));
+ return AttachUnsafe(Allocate(size, headroom, tailroom), fullSize);
+ }
+
+ /**
+ * Make a copy of the specified data
+ */
+ static TContiguousDataInternalBackend Copy(const void* data, size_t size) {
+ TContiguousDataInternalBackend result = Uninitialized(size);
+ if (size) {
+ ::memcpy(result.Data(), data, size);
+ }
+ return result;
+ }
+
+private:
+ Y_FORCE_INLINE THeader* Header() const noexcept {
+ Y_VERIFY_DEBUG(Data_);
+ return reinterpret_cast<THeader*>(Data_);
+ }
+
+ Y_FORCE_INLINE char* Data() const noexcept {
+ Y_VERIFY_DEBUG(Data_);
+ return Data_ + OverheadSize;
+ }
+
+ static bool IsPrivate(THeader* header) noexcept {
+ return 1 == AtomicGet(header->RefCount);
+ }
+
+ void AddRef() noexcept {
+ if (Data_) {
+ AtomicIncrement(Header()->RefCount);
+ }
+ }
+
+ void Release() noexcept {
+ if (Data_) {
+ auto* header = Header();
+ if (IsPrivate(header) || 0 == AtomicDecrement(header->RefCount)) {
+ Deallocate(Data_);
+ }
+ }
+ }
+
+private:
+ static size_t checkedSum(size_t a, size_t b) {
+ if (a > std::numeric_limits<size_t>::max() - b) {
+ throw std::length_error("Allocate size overflow");
+ }
+ return a + b;
+ }
+
+ static char* Allocate(size_t size, size_t headroom = 0, size_t tailroom = 0) {
+ char* data = nullptr;
+ size_t fullSize = checkedSum(size, checkedSum(headroom, tailroom));
+ if (fullSize > 0) {
+ if (fullSize >= MaxDataSize) {
+ throw std::length_error("Allocate size overflow");
+ }
+ auto allocSize = OverheadSize + fullSize;
+ char* raw = reinterpret_cast<char*>(y_allocate(allocSize));
+
+ auto* header = reinterpret_cast<THeader*>(raw);
+ header->Begin = raw + OverheadSize + headroom;
+ header->End = raw + allocSize - tailroom;
+ header->RefCount = 1;
+
+ data = raw;
+ }
+
+ return data;
+ }
+
+ static void Deallocate(char* data) noexcept {
+ if (data) {
+ char* raw = data;
+
+ y_deallocate(raw);
+ }
+ }
+
+private:
+ char* Data_;
+ size_t Size_;
+};
+
+} // namespace NDetail
diff --git a/library/cpp/actors/util/contiguous_data_ut.cpp b/library/cpp/actors/util/contiguous_data_ut.cpp
index 176b5d302f..6d7c698879 100644
--- a/library/cpp/actors/util/contiguous_data_ut.cpp
+++ b/library/cpp/actors/util/contiguous_data_ut.cpp
@@ -164,26 +164,6 @@ Y_UNIT_TEST_SUITE(TContiguousData) {
UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0);
}
- Y_UNIT_TEST(Extract) {
- TContiguousData data = TContiguousData::Uninitialized(10, 20, 30);
- NActors::TSharedData extracted = data.ExtractUnderlyingContainerOrCopy<NActors::TSharedData>();
- UNIT_ASSERT_UNEQUAL(data.data(), extracted.data());
- UNIT_ASSERT_UNEQUAL(data.data(), extracted.data() + 20);
- data = TContiguousData::Uninitialized(10);
- extracted = data.ExtractUnderlyingContainerOrCopy<NActors::TSharedData>();
- UNIT_ASSERT_EQUAL(data.data(), extracted.data());
-
- TContiguousData data2 = TContiguousData::Uninitialized(10, 20, 30);
- data2.GrowFront(20);
- extracted = data2.ExtractUnderlyingContainerOrCopy<NActors::TSharedData>();
- UNIT_ASSERT_EQUAL(data2.data(), extracted.data());
- UNIT_ASSERT_EQUAL(data2.size(), extracted.size());
- data2.GrowBack(34);
- extracted = data2.ExtractUnderlyingContainerOrCopy<NActors::TSharedData>();
- UNIT_ASSERT_EQUAL(data2.data(), extracted.data());
- UNIT_ASSERT_EQUAL(data2.size(), extracted.size());
- }
-
Y_UNIT_TEST(Reserve) {
TContiguousData data = TContiguousData::Copy("test", 4, 5, 6);
TContiguousData data2 = data;
diff --git a/library/cpp/neh/http2.cpp b/library/cpp/neh/http2.cpp
index e4b024d093..8cc693e9a3 100644
--- a/library/cpp/neh/http2.cpp
+++ b/library/cpp/neh/http2.cpp
@@ -964,8 +964,8 @@ namespace {
inline bool Get(THttpConnRef& conn, size_t addrId) {
#ifdef DEBUG_STAT
TDebugStat::ConnTotal.store(TotalConn.Val(), std::memory_order_release);
- TDebugStat::ConnActive(Active(), std::memory_order_release);
- TDebugStat::ConnCached(Cache_.Size(), std::memory_order_release);
+ TDebugStat::ConnActive.store(Active(), std::memory_order_release);
+ TDebugStat::ConnCached.store(Cache_.Size(), std::memory_order_release);
#endif
return Cache_.Get(conn, addrId);
}