aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinnokentii <innokentii@yandex-team.com>2022-11-08 10:19:21 +0300
committerinnokentii <innokentii@yandex-team.com>2022-11-08 10:19:21 +0300
commitb23296965af8123d5f9a4f6b7ad38e993b7b0575 (patch)
treef448d1368ce234d2ce80a9414c8857ad589ad318
parentbed275eb55181fa9a445a6af7d54bd49c278e5cb (diff)
downloadydb-b23296965af8123d5f9a4f6b7ad38e993b7b0575.tar.gz
Add owner-based shared_data backend impl for contiguous_data
add owner-based shared_data backend impl for contiguous_data
-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.h289
-rw-r--r--library/cpp/actors/util/contiguous_data_ut.cpp48
-rw-r--r--library/cpp/actors/util/shared_data_backtracing_owner.h8
5 files changed, 213 insertions, 183 deletions
diff --git a/library/cpp/actors/util/CMakeLists.txt b/library/cpp/actors/util/CMakeLists.txt
index 19f683cb2a..96eee91c9e 100644
--- a/library/cpp/actors/util/CMakeLists.txt
+++ b/library/cpp/actors/util/CMakeLists.txt
@@ -18,6 +18,7 @@ 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
new file mode 100644
index 0000000000..8a9cb6ef1a
--- /dev/null
+++ b/library/cpp/actors/util/contiguous_data.cpp
@@ -0,0 +1,50 @@
+#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 e161a511c2..c52ef4b7d8 100644
--- a/library/cpp/actors/util/contiguous_data.h
+++ b/library/cpp/actors/util/contiguous_data.h
@@ -11,6 +11,7 @@
#include <util/system/sanitizers.h>
#include <util/system/valgrind.h>
#include <util/generic/array_ref.h>
+#include <util/system/sys_alloc.h>
#include "shared_data.h"
@@ -294,7 +295,7 @@ class TContiguousData {
enum class EType : uintptr_t {
STRING,
SHARED_DATA,
- SHARED_DATA_CONTROLLED,
+ SHARED_DATA_CONTROLLED_BY_OWNER,
ROPE_CHUNK_BACKEND,
};
@@ -329,6 +330,44 @@ class TContiguousData {
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;
+ }
+
+ 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);
@@ -346,12 +385,9 @@ class TContiguousData {
: Owner(Construct<TString>(EType::STRING, std::move(s)))
{}
- TBackend(NActors::TSharedData s, TControlToken)
- : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA_CONTROLLED, std::move(s)))
- {}
-
TBackend(NActors::TSharedData s)
- : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA, std::move(s)))
+ : Owner(Construct<NActors::TSharedData>(
+ TSharedDataControllingOwner::CheckControlled(s.data()) ? EType::SHARED_DATA_CONTROLLED_BY_OWNER : EType::SHARED_DATA, std::move(s)))
{}
TBackend(IContiguousChunk::TPtr backend)
@@ -400,20 +436,52 @@ class TContiguousData {
return reinterpret_cast<const void*>(Owner.Data[0]);
}
+ TCookies* GetCookies() {
+ if(!Owner) {
+ return nullptr;
+ }
+ return Visit(Owner, [](EType type, 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;
+ }
+ } else {
+ return nullptr;
+ }
+ });
+ }
+
+ const TCookies* GetCookies() const {
+ return const_cast<TBackend&>(*this).GetCookies();
+ }
+
+ bool IsPrivate() const {
+ if(!Owner) {
+ return true;
+ }
+ return Visit(Owner, [](EType, auto& value) -> bool {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ return value.IsPrivate();
+ } else {
+ return false;
+ }
+ });
+ }
+
TContiguousSpan GetData() const {
if (!Owner) {
return TContiguousSpan();
}
- return Visit(Owner, [](EType type, auto& value) -> TContiguousSpan {
+ return Visit(Owner, [](EType, auto& value) -> TContiguousSpan {
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>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- return {value.data(), value.size() - CookiesSize};
- } else {
- return {value.data(), value.size()};
- }
+ return {value.data(), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->GetData();
} else {
@@ -426,7 +494,7 @@ class TContiguousData {
if (!Owner) {
return TMutableContiguousSpan();
}
- return Visit(Owner, [](EType type, auto& value) -> TMutableContiguousSpan {
+ return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, TString>) {
return {value.Detach(), value.size()};
@@ -434,11 +502,7 @@ class TContiguousData {
if (value.IsShared()) {
value = NActors::TSharedData::Copy(value.data(), value.size());
}
- if (type == EType::SHARED_DATA_CONTROLLED) {
- return {value.mutable_data(), value.size() - CookiesSize};
- } else {
- return {value.mutable_data(), value.size()};
- }
+ return {value.mutable_data(), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->GetDataMut();
} else {
@@ -451,16 +515,12 @@ class TContiguousData {
if (!Owner) {
return TMutableContiguousSpan();
}
- return Visit(Owner, [](EType type, auto& value) -> TMutableContiguousSpan {
+ return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan {
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>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- return {const_cast<char*>(value.data()), value.size() - CookiesSize};
- } else {
- return {const_cast<char*>(value.data()), value.size()};
- }
+ return {const_cast<char*>(value.data()), value.size()};
} else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
return value->UnsafeGetDataMut();
} else {
@@ -502,127 +562,59 @@ class TContiguousData {
if (!Owner) {
return false;
}
- return Visit(Owner, [contBegin = begin](EType type, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = value.data() + value.size() - CookiesSize;
- const TCookies* cookies = reinterpret_cast<const TCookies*>(begin);
- return value.IsPrivate() || cookies->Begin.load() == contBegin;
- }
- }
- return false;
- });
+ const TCookies* cookies = GetCookies();
+ return cookies && (IsPrivate() || cookies->Begin.load() == begin);
}
bool CanGrowBack(const char* end) const {
if (!Owner) {
return false;
}
- return Visit(Owner, [contEnd = end](EType type, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = value.data() + value.size() - CookiesSize;
- const TCookies* cookies = reinterpret_cast<const TCookies*>(begin);
- return value.IsPrivate() || cookies->End.load() == contEnd;
- }
- }
- return false;
- });
+ const TCookies* cookies = GetCookies();
+ return cookies && (IsPrivate() || cookies->End.load() == end);
}
void UpdateCookiesUnsafe(const char* contBegin, const char* contEnd) {
if (!Owner) {
return;
}
- return Visit(Owner, [contBegin, contEnd](EType type, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize);
- TCookies* cookies = reinterpret_cast<TCookies*>(begin);
- cookies->Begin.store(contBegin);
- cookies->End.store(contEnd);
- }
- }
- });
- }
-
- bool UpdateCookies(const char* curBegin, const char* contBegin, const char* curEnd, const char* contEnd) {
- if (!Owner) {
- return false;
+ TCookies* cookies = GetCookies();
+ if (cookies) {
+ cookies->Begin.store(contBegin);
+ cookies->End.store(contEnd);
}
- return Visit(Owner, [curBegin, contBegin, curEnd, contEnd](EType type, auto& value) mutable {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize);
- TCookies* cookies = reinterpret_cast<TCookies*>(begin);
- if(cookies->Begin.compare_exchange_weak(curBegin, contBegin)) {
- if(!cookies->End.compare_exchange_weak(curEnd, contEnd)) {
- cookies->Begin.store(curBegin); // rollback
- return false;
- }
- return true;
- }
- }
- return false;
- }
-
- return false;
- });
}
bool UpdateCookiesBegin(const char* curBegin, const char* contBegin) {
if (!Owner) {
return false;
}
- return Visit(Owner, [curBegin, contBegin](EType type, auto& value) mutable {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize);
- TCookies* cookies = reinterpret_cast<TCookies*>(begin);
- return cookies->Begin.compare_exchange_weak(curBegin, contBegin);
- }
- }
- return false;
- });
+
+ TCookies* cookies = GetCookies();
+ if (cookies) {
+ return cookies->Begin.compare_exchange_weak(curBegin, contBegin);
+ }
+ return false;
}
bool UpdateCookiesEnd(const char* curEnd, const char* contEnd) {
if (!Owner) {
return false;
}
- return Visit(Owner, [curEnd, contEnd](EType type, auto& value) mutable {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize);
- TCookies* cookies = reinterpret_cast<TCookies*>(begin);
- return cookies->End.compare_exchange_weak(curEnd, contEnd);
- }
- }
- return false;
- });
+
+ TCookies* cookies = GetCookies();
+ if (cookies) {
+ return cookies->End.compare_exchange_weak(curEnd, contEnd);
+ }
+ return false;
}
void Disown() {
if (Owner) {
const EType type = static_cast<EType>(Owner.Data[0] & TypeMask);
- if (type == EType::SHARED_DATA_CONTROLLED) {
- bool isPrivate = Visit(Owner, [](EType type, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- return value.IsPrivate();
- }
- }
- return false;
- });
- if (!isPrivate) {
+ if (type == EType::SHARED_DATA_CONTROLLED_BY_OWNER) {
+ if (IsPrivate()) {
Owner.Data[0] = (Owner.Data[0] & ValueMask) | static_cast<uintptr_t>(EType::SHARED_DATA);
}
}
@@ -634,16 +626,9 @@ class TContiguousData {
if (!Owner) {
return TResult{};
}
- return Visit(Owner, [](EType type, auto& value) {
+ return Visit(Owner, [](EType, auto& value) {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, TResult>) {
- if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (type == EType::SHARED_DATA_CONTROLLED) {
- NActors::TSharedData data = value;
- data.Trim(data.size() - CookiesSize);
- return data;
- }
- }
return value;
} else {
Y_FAIL();
@@ -682,15 +667,15 @@ class TContiguousData {
};
template<typename TObject>
- static TBackendHolder Construct(EType type, TObject object) {
+ static TBackendHolder Construct(EType type, TObject&& object) {
if constexpr (sizeof(TObject) <= sizeof(TBackendHolder)) {
TBackendHolder res = TBackend::Empty;
- new(&res) TObject(std::move(object));
+ new(&res) std::decay_t<TObject>(std::forward<TObject>(object));
Y_VERIFY_DEBUG((res.Data[0] & ValueMask) == res.Data[0]);
res.Data[0] = res.Data[0] | static_cast<uintptr_t>(type);
return res;
} else {
- return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::move(object)));
+ return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::forward<TObject>(object)));
}
}
@@ -721,10 +706,10 @@ class TContiguousData {
}
};
switch (type) {
- case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value));
- case EType::SHARED_DATA_CONTROLLED: [[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::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));
}
Y_FAIL("Unexpected type# %" PRIu64, static_cast<ui64>(type));
}
@@ -762,14 +747,15 @@ class TContiguousData {
const char *Begin; // data start
const char *End; // data end
- explicit TContiguousData(NActors::TSharedData s, TBackend::TCookies* cookies, TBackend::TControlToken)
- : Backend(std::move(s), TBackend::ControlToken)
+ explicit TContiguousData(NActors::TSharedData s, const char *data, size_t size, TBackend::TControlToken)
+ : Backend(std::move(s))
{
- auto span = Backend.GetData();
- Begin = span.data();
- End = Begin + span.size();
- cookies->Begin.store(Begin);
- cookies->End.store(End);
+ 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));
+ Begin = data;
+ End = data + size;
}
TContiguousData(TOwnedSlice, const char *data, size_t size, const TContiguousData& from)
@@ -850,7 +836,6 @@ public:
Y_VERIFY(data >= from.GetData());
Y_VERIFY(data < from.GetData() + from.GetSize());
Y_VERIFY(data + size <= from.GetData() + from.GetSize());
- Backend.Disown();
}
TContiguousData(TSlice, const char *begin, const char *end, const TContiguousData& from)
@@ -878,10 +863,9 @@ public:
return TContiguousData();
}
if (headroom == 0 && tailroom == 0) {
+ NActors::TSharedData res = NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size), size);
#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
- NActors::TSharedData res = TBackTracingOwner::Allocate(size, TBackTracingOwner::INFO_ALLOC_UNINITIALIZED);
-#else
- NActors::TSharedData res = NActors::TSharedData::Uninitialized(size);
+ TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINITIALIZED);
#endif
return TContiguousData(
OwnedSlice,
@@ -889,27 +873,19 @@ public:
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
- NActors::TSharedData res = TBackTracingOwner::Allocate(TBackend::TCookies::BytesToAlloc(size + headroom + tailroom), TBackTracingOwner::INFO_ALLOC_UNINIT_ROOMS);
-#else
- NActors::TSharedData res = NActors::TSharedData::Uninitialized(TBackend::TCookies::BytesToAlloc(size + headroom + tailroom));
+ TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINIT_ROOMS);
#endif
- auto isAligned = [](const void * ptr, std::uintptr_t alignment) noexcept {
- auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
- return !(iptr % alignment);
- };
- char* place = res.mutable_data() + res.size() - sizeof(TBackend::TCookies);
- Y_VERIFY(isAligned(place, alignof(TBackend::TCookies)));
- TBackend::TCookies* cookies = new(place) TBackend::TCookies();
-
- return TContiguousData(
- OwnedSlice,
- res.data() + headroom,
- res.data() + headroom + size,
- TContiguousData(res, cookies, TBackend::ControlToken));
+ return TContiguousData(res, res.data() + headroom, size, TBackend::ControlToken);
}
}
+ 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>();
@@ -1088,7 +1064,6 @@ public:
void Trim(size_t size, size_t frontOffset = 0) {
Y_VERIFY(size <= End - Begin - frontOffset);
- Backend.Disown();
Begin = Begin + frontOffset;
End = Begin + size;
}
diff --git a/library/cpp/actors/util/contiguous_data_ut.cpp b/library/cpp/actors/util/contiguous_data_ut.cpp
index f2378a4775..b7b9029f85 100644
--- a/library/cpp/actors/util/contiguous_data_ut.cpp
+++ b/library/cpp/actors/util/contiguous_data_ut.cpp
@@ -54,27 +54,27 @@ Y_UNIT_TEST_SUITE(TContiguousData) {
TContiguousData data = TContiguousData::Uninitialized(10, 20, 30);
UNIT_ASSERT_EQUAL(data.size(), 10);
UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*));
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom());
data.GrowFront(5);
UNIT_ASSERT_EQUAL(data.size(), 15);
UNIT_ASSERT_EQUAL(data.Headroom(), 15);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*));
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom());
data.GrowBack(5);
UNIT_ASSERT_EQUAL(data.size(), 20);
UNIT_ASSERT_EQUAL(data.Headroom(), 15);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 29);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*));
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 25);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom());
data.GrowFront(21);
UNIT_ASSERT_EQUAL(data.size(), 41);
UNIT_ASSERT_EQUAL(data.Headroom(), 0);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 31);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 88);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*));
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 25);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 66);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom());
data.GrowBack(32);
UNIT_ASSERT_EQUAL(data.size(), 73);
UNIT_ASSERT_EQUAL(data.Headroom(), 0);
@@ -89,30 +89,30 @@ Y_UNIT_TEST_SUITE(TContiguousData) {
UNIT_ASSERT_EQUAL(data.data(), otherData.data());
UNIT_ASSERT_EQUAL(data.size(), 10);
UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
UNIT_ASSERT_EQUAL(otherData.size(), 10);
UNIT_ASSERT_EQUAL(otherData.Headroom(), 20);
- UNIT_ASSERT_EQUAL(otherData.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 80);
+ UNIT_ASSERT_EQUAL(otherData.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 60);
data.GrowFront(5);
data.GrowBack(5);
UNIT_ASSERT_EQUAL(data.data() + 5, otherData.data());
UNIT_ASSERT_EQUAL(data.size(), 20);
UNIT_ASSERT_EQUAL(data.Headroom(), 15);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 29);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 25);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
otherData.GrowFront(5);
UNIT_ASSERT_UNEQUAL(data.data(), otherData.data());
UNIT_ASSERT_EQUAL(otherData.size(), 15);
UNIT_ASSERT_EQUAL(otherData.Headroom(), 15);
- UNIT_ASSERT_EQUAL(otherData.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 80);
+ UNIT_ASSERT_EQUAL(otherData.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 60);
data.Trim(10, 5);
UNIT_ASSERT_EQUAL(data.size(), 10);
UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 34);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80);
+ UNIT_ASSERT_EQUAL(data.Tailroom(), 30);
+ UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
}
Y_UNIT_TEST(Trim) {
@@ -120,7 +120,7 @@ Y_UNIT_TEST_SUITE(TContiguousData) {
TContiguousData otherData(data);
otherData.Trim(5);
UNIT_ASSERT_EQUAL(data.data(), otherData.data());
- UNIT_ASSERT_EQUAL(otherData.Headroom(), 0);
+ UNIT_ASSERT_EQUAL(otherData.Headroom(), 20);
UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0);
TContiguousData otherData2(data);
otherData2.Trim(1, 1);
@@ -146,7 +146,7 @@ Y_UNIT_TEST_SUITE(TContiguousData) {
Y_UNIT_TEST(SliceUnshare) {
TContiguousData data = TContiguousData::Uninitialized(10, 20, 30);
- TContiguousData otherData(TContiguousData::Slice, data.data(), data.size(), data);
+ TContiguousData otherData(TContiguousData::Slice, data.data() + 1, data.size() - 2, data);
UNIT_ASSERT_EQUAL(otherData.Headroom(), 0);
UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0);
}
diff --git a/library/cpp/actors/util/shared_data_backtracing_owner.h b/library/cpp/actors/util/shared_data_backtracing_owner.h
index 9e93e327c3..ea479d5fd1 100644
--- a/library/cpp/actors/util/shared_data_backtracing_owner.h
+++ b/library/cpp/actors/util/shared_data_backtracing_owner.h
@@ -24,7 +24,7 @@ public:
static constexpr const char* INFO_ALLOC_UNINITIALIZED = "ALLOC_UNINITIALIZED";
static constexpr const char* INFO_ALLOC_UNINIT_ROOMS = "ALLOC_UNINIT_ROOMS";
- static NActors::TSharedData Allocate(size_t size, const char* info = nullptr) {
+ static char* Allocate(size_t size, const char* info = nullptr) {
char* raw = reinterpret_cast<char*>(y_allocate(OverheadSize + size));
THeader* header = reinterpret_cast<THeader*>(raw + PrivateHeaderSize);
TSelf* btOwner = new TSelf;
@@ -33,7 +33,7 @@ public:
header->RefCount = 1;
header->Owner = btOwner;
char* data = raw + OverheadSize;
- return NActors::TSharedData::AttachUnsafe(data, size);
+ return data;
}
static void FakeOwner(const NActors::TSharedData& data, const char* info = nullptr) {
@@ -68,6 +68,10 @@ public:
delete this;
}
+ IOwner* GetRealOwner() const {
+ return RealOwner;
+ }
+
void PrintBackTrace() {
Cerr << "Deallocate TSharedData with info# " << Info << Endl;
BackTrace.PrintTo(Cerr);