aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authoralexvru <alexvru@ydb.tech>2023-08-03 10:50:52 +0300
committeralexvru <alexvru@ydb.tech>2023-08-03 10:50:52 +0300
commite0ff37fbb9f0dbd6a20932a40b72e79dd77b572b (patch)
tree6a5ed43c96c6bbc501ffece029e08966242d5fd3 /library/cpp
parent6c82f53a066b2d61863529956787639fce914fbf (diff)
downloadydb-e0ff37fbb9f0dbd6a20932a40b72e79dd77b572b.tar.gz
Fix Compact to support undetached containers KIKIMR-18902
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/actors/util/rc_buf.h39
-rw-r--r--library/cpp/actors/util/shared_data_rope_backend.h4
2 files changed, 34 insertions, 9 deletions
diff --git a/library/cpp/actors/util/rc_buf.h b/library/cpp/actors/util/rc_buf.h
index 11a09f5b9a..7b6c68d269 100644
--- a/library/cpp/actors/util/rc_buf.h
+++ b/library/cpp/actors/util/rc_buf.h
@@ -294,6 +294,13 @@ struct IContiguousChunk : TThrRefBase {
return GetDataMut();
}
+ /**
+ * Should return true if GetDataMut() would not copy contents when called.
+ */
+ virtual bool IsPrivate() const {
+ return true;
+ }
+
virtual size_t GetOccupiedMemorySize() const = 0;
};
@@ -434,8 +441,12 @@ class TRcBuf {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, NActors::TSharedData> || std::is_same_v<T, TInternalBackend>) {
return value.IsPrivate();
+ } else if constexpr (std::is_same_v<T, TString>) {
+ return value.IsDetached();
+ } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
+ return value.RefCount() == 1 && value->IsPrivate();
} else {
- return false;
+ static_assert(TDependentFalse<T>);
}
});
}
@@ -865,14 +876,20 @@ public:
return Begin;
}
- char* GetDataMut() {
- const char* oldBegin = Backend.GetData().data();
- ptrdiff_t offset = Begin - oldBegin;
- size_t size = GetSize();
- char* newBegin = Backend.GetDataMut().data();
- Begin = newBegin + offset;
- End = Begin + size;
- return newBegin + offset;
+ char* GetDataMut(size_t headroom = 0, size_t tailroom = 0) {
+ const TContiguousSpan backendData = Backend.GetData();
+ if (IsPrivate() || (backendData.data() == GetData() && backendData.size() == GetSize())) { // if we own container or reference it whole
+ const char* oldBegin = backendData.data();
+ ptrdiff_t offset = Begin - oldBegin;
+ size_t size = GetSize();
+ char* newBegin = Backend.GetDataMut().data();
+ Begin = newBegin + offset;
+ End = Begin + size;
+ return newBegin + offset;
+ } else { // make a copy of referenced data
+ *this = Copy(GetContiguousSpan(), headroom, tailroom);
+ return Backend.GetDataMut().data();
+ }
}
char* UnsafeGetDataMut() {
@@ -1064,6 +1081,10 @@ public:
return GetDataMut();
}
+ bool IsPrivate() const {
+ return Backend.IsPrivate();
+ }
+
size_t UnsafeHeadroom() const {
return Begin - Backend.GetData().data();
}
diff --git a/library/cpp/actors/util/shared_data_rope_backend.h b/library/cpp/actors/util/shared_data_rope_backend.h
index 2abfcf5584..a221ae668b 100644
--- a/library/cpp/actors/util/shared_data_rope_backend.h
+++ b/library/cpp/actors/util/shared_data_rope_backend.h
@@ -29,6 +29,10 @@ public:
return {const_cast<char *>(Buffer.data()), Buffer.size()};
}
+ bool IsPrivate() const override {
+ return Buffer.IsPrivate();
+ }
+
size_t GetOccupiedMemorySize() const override {
return Buffer.size();
}