aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/util
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2023-12-04 15:32:14 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2023-12-05 01:22:50 +0300
commitc21ed9eedf73010bc81342518177dfdfb0d56bd7 (patch)
tree72f8fde4463080cfe5a38eb0babc051cfe32c51e /library/cpp/actors/util
parentec1311bf2e8cc231723b8b5e484ca576663a1309 (diff)
downloadydb-c21ed9eedf73010bc81342518177dfdfb0d56bd7.tar.gz
Intermediate changes
Diffstat (limited to 'library/cpp/actors/util')
-rw-r--r--library/cpp/actors/util/CMakeLists.darwin-arm64.txt28
-rw-r--r--library/cpp/actors/util/CMakeLists.darwin-x86_64.txt28
-rw-r--r--library/cpp/actors/util/CMakeLists.linux-aarch64.txt29
-rw-r--r--library/cpp/actors/util/CMakeLists.linux-x86_64.txt29
-rw-r--r--library/cpp/actors/util/CMakeLists.txt19
-rw-r--r--library/cpp/actors/util/CMakeLists.windows-x86_64.txt28
-rw-r--r--library/cpp/actors/util/README.md99
-rw-r--r--library/cpp/actors/util/affinity.cpp93
-rw-r--r--library/cpp/actors/util/affinity.h49
-rw-r--r--library/cpp/actors/util/cpu_load_log.h227
-rw-r--r--library/cpp/actors/util/cpu_load_log_ut.cpp275
-rw-r--r--library/cpp/actors/util/cpumask.h133
-rw-r--r--library/cpp/actors/util/datetime.h82
-rw-r--r--library/cpp/actors/util/defs.h16
-rw-r--r--library/cpp/actors/util/funnel_queue.h240
-rw-r--r--library/cpp/actors/util/futex.h13
-rw-r--r--library/cpp/actors/util/intrinsics.h97
-rw-r--r--library/cpp/actors/util/local_process_key.h157
-rw-r--r--library/cpp/actors/util/memory_track.cpp38
-rw-r--r--library/cpp/actors/util/memory_track.h293
-rw-r--r--library/cpp/actors/util/memory_tracker.cpp103
-rw-r--r--library/cpp/actors/util/memory_tracker.h53
-rw-r--r--library/cpp/actors/util/memory_tracker_ut.cpp263
-rw-r--r--library/cpp/actors/util/named_tuple.h30
-rw-r--r--library/cpp/actors/util/queue_chunk.h29
-rw-r--r--library/cpp/actors/util/queue_oneone_inplace.h118
-rw-r--r--library/cpp/actors/util/rc_buf.cpp6
-rw-r--r--library/cpp/actors/util/rc_buf.h1120
-rw-r--r--library/cpp/actors/util/rc_buf_backend.h230
-rw-r--r--library/cpp/actors/util/rc_buf_ut.cpp207
-rw-r--r--library/cpp/actors/util/recentwnd.h67
-rw-r--r--library/cpp/actors/util/rope.cpp13
-rw-r--r--library/cpp/actors/util/rope.h1148
-rw-r--r--library/cpp/actors/util/rope_cont_embedded_list.h391
-rw-r--r--library/cpp/actors/util/rope_ut.cpp418
-rw-r--r--library/cpp/actors/util/shared_data.cpp49
-rw-r--r--library/cpp/actors/util/shared_data.h227
-rw-r--r--library/cpp/actors/util/shared_data_backtracing_owner.h88
-rw-r--r--library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp231
-rw-r--r--library/cpp/actors/util/shared_data_rope_backend.h41
-rw-r--r--library/cpp/actors/util/shared_data_rope_backend_ut.cpp231
-rw-r--r--library/cpp/actors/util/shared_data_ut.cpp205
-rw-r--r--library/cpp/actors/util/should_continue.cpp23
-rw-r--r--library/cpp/actors/util/should_continue.h22
-rw-r--r--library/cpp/actors/util/thread.h26
-rw-r--r--library/cpp/actors/util/thread_load_log.h363
-rw-r--r--library/cpp/actors/util/thread_load_log_ut.cpp966
-rw-r--r--library/cpp/actors/util/threadparkpad.cpp152
-rw-r--r--library/cpp/actors/util/threadparkpad.h21
-rw-r--r--library/cpp/actors/util/ticket_lock.h48
-rw-r--r--library/cpp/actors/util/timerfd.h65
-rw-r--r--library/cpp/actors/util/unordered_cache.h201
-rw-r--r--library/cpp/actors/util/unordered_cache_ut.cpp138
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.darwin-arm64.txt74
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.darwin-x86_64.txt75
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.linux-aarch64.txt78
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.linux-x86_64.txt80
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.txt19
-rw-r--r--library/cpp/actors/util/ut/CMakeLists.windows-x86_64.txt68
-rw-r--r--library/cpp/actors/util/ut/ya.make20
-rw-r--r--library/cpp/actors/util/ut_helpers.h12
-rw-r--r--library/cpp/actors/util/ya.make50
62 files changed, 0 insertions, 9742 deletions
diff --git a/library/cpp/actors/util/CMakeLists.darwin-arm64.txt b/library/cpp/actors/util/CMakeLists.darwin-arm64.txt
deleted file mode 100644
index be68d418f7..0000000000
--- a/library/cpp/actors/util/CMakeLists.darwin-arm64.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-add_subdirectory(ut)
-
-add_library(cpp-actors-util)
-target_link_libraries(cpp-actors-util PUBLIC
- contrib-libs-cxxsupp
- yutil
- cpp-containers-absl_flat_hash
- cpp-deprecated-atomic
- library-cpp-pop_count
-)
-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/rope.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf.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/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/util/CMakeLists.darwin-x86_64.txt
deleted file mode 100644
index be68d418f7..0000000000
--- a/library/cpp/actors/util/CMakeLists.darwin-x86_64.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-add_subdirectory(ut)
-
-add_library(cpp-actors-util)
-target_link_libraries(cpp-actors-util PUBLIC
- contrib-libs-cxxsupp
- yutil
- cpp-containers-absl_flat_hash
- cpp-deprecated-atomic
- library-cpp-pop_count
-)
-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/rope.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf.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/CMakeLists.linux-aarch64.txt b/library/cpp/actors/util/CMakeLists.linux-aarch64.txt
deleted file mode 100644
index 9c5183c2bd..0000000000
--- a/library/cpp/actors/util/CMakeLists.linux-aarch64.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-add_subdirectory(ut)
-
-add_library(cpp-actors-util)
-target_link_libraries(cpp-actors-util PUBLIC
- contrib-libs-linux-headers
- contrib-libs-cxxsupp
- yutil
- cpp-containers-absl_flat_hash
- cpp-deprecated-atomic
- library-cpp-pop_count
-)
-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/rope.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf.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/CMakeLists.linux-x86_64.txt b/library/cpp/actors/util/CMakeLists.linux-x86_64.txt
deleted file mode 100644
index 9c5183c2bd..0000000000
--- a/library/cpp/actors/util/CMakeLists.linux-x86_64.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-add_subdirectory(ut)
-
-add_library(cpp-actors-util)
-target_link_libraries(cpp-actors-util PUBLIC
- contrib-libs-linux-headers
- contrib-libs-cxxsupp
- yutil
- cpp-containers-absl_flat_hash
- cpp-deprecated-atomic
- library-cpp-pop_count
-)
-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/rope.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf.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/CMakeLists.txt b/library/cpp/actors/util/CMakeLists.txt
deleted file mode 100644
index 2dce3a77fe..0000000000
--- a/library/cpp/actors/util/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
- include(CMakeLists.linux-aarch64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
- include(CMakeLists.darwin-x86_64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
- include(CMakeLists.darwin-arm64.txt)
-elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
- include(CMakeLists.windows-x86_64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
- include(CMakeLists.linux-x86_64.txt)
-endif()
diff --git a/library/cpp/actors/util/CMakeLists.windows-x86_64.txt b/library/cpp/actors/util/CMakeLists.windows-x86_64.txt
deleted file mode 100644
index be68d418f7..0000000000
--- a/library/cpp/actors/util/CMakeLists.windows-x86_64.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-add_subdirectory(ut)
-
-add_library(cpp-actors-util)
-target_link_libraries(cpp-actors-util PUBLIC
- contrib-libs-cxxsupp
- yutil
- cpp-containers-absl_flat_hash
- cpp-deprecated-atomic
- library-cpp-pop_count
-)
-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/rope.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf.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/README.md b/library/cpp/actors/util/README.md
deleted file mode 100644
index ff2d573fe8..0000000000
--- a/library/cpp/actors/util/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-## Memory tracker
-
-https://a.yandex-team.ru/arc/trunk/arcadia/library/cpp/actors/util/memory_track.h
-
-Использование:
-
-* отслеживание аллокаций экземпляров конкретного класса через new/delete и new[]/delete[]
-* отслеживание аллокаций в контейнерах
-* ручное отслеживание моментов аллокации/деаллокации
-
-----
-
-### Отслеживание аллокаций класса через new/delete
-
-Использование с автоматически генерируемой меткой:
-
-```cpp
-#include <library/cpp/actors/util/memory_track.h>
-
-struct TTypeLabeled
- : public NActors::NMemory::TTrack<TTypeLabeled>
-{
- char payload[16];
-};
-```
-
-Использование с пользовательским именем метки:
-
-```cpp
-#include <library/cpp/actors/util/memory_track.h>
-
-static const char NamedLabel[] = "NamedLabel";
-
-struct TNameLabeled
- : public NActors::NMemory::TTrack<TNameLabeled, NamedLabel>
-{
- char payload[32];
-};
-```
-
-----
-
-### Отслеживание аллокаций в контейнерах
-
-```cpp
-#include <library/cpp/actors/util/memory_track.h>
-
-static const char InContainerLabel[] = "InContainerLabel";
-
-struct TInContainer {
- char payload[16];
-};
-
-std::vector<TInContainer, NActors::NMemory::TAlloc<TInContainer>> vecT;
-
-std::vector<TInContainer, NActors::NMemory::TAlloc<TInContainer, InContainerLabel>> vecN;
-
-using TKey = int;
-
-std::map<TKey, TInContainer, std::less<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>>> mapT;
-
-std::map<TKey, TInContainer, std::less<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>, InContainerLabel>> mapN;
-
-std::unordered_map<TKey, TInContainer, std::hash<TKey>, std::equal_to<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>>> umapT;
-
-std::unordered_map<TKey, TInContainer, std::hash<TKey>, std::equal_to<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>, InContainerLabel>> umapN;
-```
-
-----
-
-### Ручное отслеживание аллокаций/деаллокаций
-
-```cpp
-#include <library/cpp/actors/util/memory_track.h>
-
-static const char ManualLabel[] = "ManualLabel";
-
-...
-NActors::NMemory::TLabel<ManualLabel>::Add(size);
-
-...
-NActors::NMemory::TLabel<ManualLabel>::Sub(size);
-```
-
-----
-
-### Собираемые метрики
-
-Сервис **utils**, пользовательская метка **label**, сенсоры:
-
-- MT/Count: количество аллокаций в моменте
-- MT/Memory: аллоцированная память в моменте
-- MT/PeakCount: пиковое значение количества аллокаций (сэмплится с фиксированной частотой)
-- MT/PeakMemory: пиковое значение аллоцированной памяти
-
diff --git a/library/cpp/actors/util/affinity.cpp b/library/cpp/actors/util/affinity.cpp
deleted file mode 100644
index 5851105ae7..0000000000
--- a/library/cpp/actors/util/affinity.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "affinity.h"
-
-#ifdef _linux_
-#include <sched.h>
-#endif
-
-class TAffinity::TImpl {
-#ifdef _linux_
- cpu_set_t Mask;
-#endif
-public:
- TImpl() {
-#ifdef _linux_
- int ar = sched_getaffinity(0, sizeof(cpu_set_t), &Mask);
- Y_DEBUG_ABORT_UNLESS(ar == 0);
-#endif
- }
-
- explicit TImpl(const ui8* cpus, ui32 size) {
-#ifdef _linux_
- CPU_ZERO(&Mask);
- for (ui32 i = 0; i != size; ++i) {
- if (cpus[i]) {
- CPU_SET(i, &Mask);
- }
- }
-#else
- Y_UNUSED(cpus);
- Y_UNUSED(size);
-#endif
- }
-
- void Set() const {
-#ifdef _linux_
- int ar = sched_setaffinity(0, sizeof(cpu_set_t), &Mask);
- Y_DEBUG_ABORT_UNLESS(ar == 0);
-#endif
- }
-
- operator TCpuMask() const {
- TCpuMask result;
-#ifdef _linux_
- for (ui32 i = 0; i != CPU_SETSIZE; ++i) {
- result.Cpus.emplace_back(CPU_ISSET(i, &Mask));
- }
- result.RemoveTrailingZeros();
-#endif
- return result;
- }
-
-};
-
-TAffinity::TAffinity() {
-}
-
-TAffinity::~TAffinity() {
-}
-
-TAffinity::TAffinity(const ui8* x, ui32 sz) {
- if (x && sz) {
- Impl.Reset(new TImpl(x, sz));
- }
-}
-
-TAffinity::TAffinity(const TCpuMask& mask) {
- if (!mask.IsEmpty()) {
- static_assert(sizeof(ui8) == sizeof(mask.Cpus[0]));
- const ui8* x = reinterpret_cast<const ui8*>(&mask.Cpus[0]);
- const ui32 sz = mask.Size();
- Impl.Reset(new TImpl(x, sz));
- }
-}
-
-void TAffinity::Current() {
- Impl.Reset(new TImpl());
-}
-
-void TAffinity::Set() const {
- if (!!Impl) {
- Impl->Set();
- }
-}
-
-bool TAffinity::Empty() const {
- return !Impl;
-}
-
-TAffinity::operator TCpuMask() const {
- if (!!Impl) {
- return *Impl;
- }
- return TCpuMask();
-}
diff --git a/library/cpp/actors/util/affinity.h b/library/cpp/actors/util/affinity.h
deleted file mode 100644
index ae106ed180..0000000000
--- a/library/cpp/actors/util/affinity.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-#include "defs.h"
-#include "cpumask.h"
-
-// Platform-specific class to set or get thread affinity
-class TAffinity: public TThrRefBase, TNonCopyable {
- class TImpl;
- THolder<TImpl> Impl;
-
-public:
- TAffinity();
- TAffinity(const ui8* cpus, ui32 size);
- explicit TAffinity(const TCpuMask& mask);
- ~TAffinity();
-
- void Current();
- void Set() const;
- bool Empty() const;
-
- operator TCpuMask() const;
-};
-
-// Scoped affinity setter
-class TAffinityGuard : TNonCopyable {
- bool Stacked;
- TAffinity OldAffinity;
-
-public:
- TAffinityGuard(const TAffinity* affinity) {
- Stacked = false;
- if (affinity && !affinity->Empty()) {
- OldAffinity.Current();
- affinity->Set();
- Stacked = true;
- }
- }
-
- ~TAffinityGuard() {
- Release();
- }
-
- void Release() {
- if (Stacked) {
- OldAffinity.Set();
- Stacked = false;
- }
- }
-};
diff --git a/library/cpp/actors/util/cpu_load_log.h b/library/cpp/actors/util/cpu_load_log.h
deleted file mode 100644
index 225f7148da..0000000000
--- a/library/cpp/actors/util/cpu_load_log.h
+++ /dev/null
@@ -1,227 +0,0 @@
-#pragma once
-
-#include "defs.h"
-#include <library/cpp/deprecated/atomic/atomic.h>
-#include <library/cpp/pop_count/popcount.h>
-
-static constexpr ui64 BitDurationNs = 131'072; // A power of 2
-
-template <ui64 DataSize>
-struct TCpuLoadLog {
- static constexpr ui64 BitsSize = DataSize * 64;
- TAtomic LastTimeNs = 0;
- ui64 Data[DataSize];
-
- TCpuLoadLog() {
- LastTimeNs = 0;
- for (size_t i = 0; i < DataSize; ++i) {
- Data[i] = 0;
- }
- }
-
- TCpuLoadLog(ui64 timeNs) {
- LastTimeNs = timeNs;
- for (size_t i = 0; i < DataSize; ++i) {
- Data[i] = 0;
- }
- }
-
- void RegisterBusyPeriod(ui64 timeNs) {
- RegisterBusyPeriod<true>(timeNs, AtomicGet(LastTimeNs));
- }
-
- template <bool ModifyLastTime>
- void RegisterBusyPeriod(ui64 timeNs, ui64 lastTimeNs) {
- timeNs |= 1ull;
- if (timeNs < lastTimeNs) {
- for (ui64 i = 0; i < DataSize; ++i) {
- AtomicSet(Data[i], ~0ull);
- }
- if (ModifyLastTime) {
- AtomicSet(LastTimeNs, timeNs);
- }
- return;
- }
- const ui64 lastIdx = timeNs / BitDurationNs;
- const ui64 curIdx = lastTimeNs / BitDurationNs;
- ui64 firstElementIdx = curIdx / 64;
- const ui64 firstBitIdx = curIdx % 64;
- const ui64 lastElementIdx = lastIdx / 64;
- const ui64 lastBitIdx = lastIdx % 64;
- if (firstElementIdx == lastElementIdx) {
- ui64 prevValue = 0;
- if (firstBitIdx != 0) {
- prevValue = AtomicGet(Data[firstElementIdx % DataSize]);
- }
- const ui64 bits = (((~0ull) << (firstBitIdx + (63-lastBitIdx))) >> (63-lastBitIdx));
- const ui64 newValue = prevValue | bits;
- AtomicSet(Data[firstElementIdx % DataSize], newValue);
- if (ModifyLastTime) {
- AtomicSet(LastTimeNs, timeNs);
- }
- return;
- }
- // process the first element
- ui64 prevValue = 0;
- if (firstBitIdx != 0) {
- prevValue = AtomicGet(Data[firstElementIdx % DataSize]);
- }
- const ui64 bits = ((~0ull) << firstBitIdx);
- const ui64 newValue = (prevValue | bits);
- AtomicSet(Data[firstElementIdx % DataSize], newValue);
- ++firstElementIdx;
- // process the fully filled elements
- const ui64 firstLoop = firstElementIdx / DataSize;
- const ui64 lastLoop = lastElementIdx / DataSize;
- const ui64 lastOffset = lastElementIdx % DataSize;
- if (firstLoop < lastLoop) {
- for (ui64 i = firstElementIdx % DataSize; i < DataSize; ++i) {
- AtomicSet(Data[i], ~0ull);
- }
- for (ui64 i = 0; i < lastOffset; ++i) {
- AtomicSet(Data[i], ~0ull);
- }
- } else {
- for (ui64 i = firstElementIdx % DataSize; i < lastOffset; ++i) {
- AtomicSet(Data[i], ~0ull);
- }
- }
- // process the last element
- const ui64 newValue2 = ((~0ull) >> (63-lastBitIdx));
- AtomicSet(Data[lastOffset], newValue2);
- if (ModifyLastTime) {
- AtomicSet(LastTimeNs, timeNs);
- }
- }
-
- void RegisterIdlePeriod(ui64 timeNs) {
- timeNs &= ~1ull;
- ui64 lastTimeNs = AtomicGet(LastTimeNs);
- if (timeNs < lastTimeNs) {
- // Fast check first, slower chec later
- if ((timeNs | 1ull) < lastTimeNs) {
- // Time goes back, dont panic, just mark the whole array 'busy'
- for (ui64 i = 0; i < DataSize; ++i) {
- AtomicSet(Data[i], ~0ull);
- }
- AtomicSet(LastTimeNs, timeNs);
- return;
- }
- }
- const ui64 curIdx = lastTimeNs / BitDurationNs;
- const ui64 lastIdx = timeNs / BitDurationNs;
- ui64 firstElementIdx = curIdx / 64;
- const ui64 lastElementIdx = lastIdx / 64;
- if (firstElementIdx >= lastElementIdx) {
- AtomicSet(LastTimeNs, timeNs);
- return;
- }
- // process the first partially filled element
- ++firstElementIdx;
- // process all other elements
- const ui64 firstLoop = firstElementIdx / DataSize;
- const ui64 lastLoop = lastElementIdx / DataSize;
- const ui64 lastOffset = lastElementIdx % DataSize;
- if (firstLoop < lastLoop) {
- for (ui64 i = firstElementIdx % DataSize; i < DataSize; ++i) {
- AtomicSet(Data[i], 0);
- }
- for (ui64 i = 0; i <= lastOffset; ++i) {
- AtomicSet(Data[i], 0);
- }
- } else {
- for (ui64 i = firstElementIdx % DataSize; i <= lastOffset; ++i) {
- AtomicSet(Data[i], 0);
- }
- }
- AtomicSet(LastTimeNs, timeNs);
- }
-};
-
-template <ui64 DataSize>
-struct TMinusOneCpuEstimator {
- static constexpr ui64 BitsSize = DataSize * 64;
- ui64 BeginDelayIdx;
- ui64 EndDelayIdx;
- ui64 Idle;
- ui64 Delay[BitsSize];
-
- ui64 MaxLatencyIncreaseWithOneLessCpu(TCpuLoadLog<DataSize>** logs, i64 logCount, ui64 timeNs, ui64 periodNs) {
- Y_ABORT_UNLESS(logCount > 0);
- ui64 endTimeNs = timeNs;
-
- ui64 lastTimeNs = timeNs;
- for (i64 log_idx = 0; log_idx < logCount; ++log_idx) {
- ui64 x = AtomicGet(logs[log_idx]->LastTimeNs);
- if ((x & 1) == 1) {
- lastTimeNs = Min(lastTimeNs, x);
- } else {
- logs[log_idx]->template RegisterBusyPeriod<false>(endTimeNs, x);
- }
- }
- const ui64 beginTimeNs = periodNs < timeNs ? timeNs - periodNs : 0;
-
- ui64 beginIdx = beginTimeNs / BitDurationNs;
- ui64 lastIdx = lastTimeNs / BitDurationNs;
- ui64 beginElementIdx = beginIdx / 64;
- ui64 lastElementIdx = lastIdx / 64;
-
- BeginDelayIdx = 0;
- EndDelayIdx = 0;
- Idle = 0;
- ui64 maxDelay = 0;
- ui64 bucket = 0;
- for (ui64 idx = beginElementIdx; idx <= lastElementIdx; ++idx) {
- ui64 i = idx % DataSize;
- ui64 input = AtomicGet(logs[0]->Data[i]);
- ui64 all_busy = ~0ull;
- for (i64 log_idx = 1; log_idx < logCount; ++log_idx) {
- ui64 x = AtomicGet(logs[log_idx]->Data[i]);
- all_busy &= x;
- }
- if (!input) {
- if (!bucket) {
- Idle += 64 - PopCount(all_busy);
- continue;
- }
- }
- for (i64 bit_idx = 0; bit_idx < 64; ++bit_idx) {
- ui64 x = (1ull << bit_idx);
- if (all_busy & x) {
- if (input & x) {
- // Push into the queue
- bucket++;
- Delay[EndDelayIdx] = EndDelayIdx;
- ++EndDelayIdx;
- } else {
- // All busy
- }
- } else {
- if (input & x) {
- // Move success
- } else {
- if (bucket) {
- // Remove from the queue
- bucket--;
- ui64 stored = Delay[BeginDelayIdx];
- ++BeginDelayIdx;
- ui64 delay = EndDelayIdx - stored;
- maxDelay = Max(maxDelay, delay);
- //Cerr << "bit_idx: " << bit_idx << " stored: " << stored << " delay: " << delay << Endl;
- } else {
- Idle++;
- }
- }
- }
- }
- }
- if (bucket) {
- ui64 stored = Delay[BeginDelayIdx];
- ui64 delay = EndDelayIdx - stored;
- maxDelay = Max(maxDelay, delay);
- //Cerr << "last stored: " << stored << " delay: " << delay << Endl;
- }
- return maxDelay * BitDurationNs;
- }
-};
-
diff --git a/library/cpp/actors/util/cpu_load_log_ut.cpp b/library/cpp/actors/util/cpu_load_log_ut.cpp
deleted file mode 100644
index 7109123c6e..0000000000
--- a/library/cpp/actors/util/cpu_load_log_ut.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-#include "cpu_load_log.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-#include <util/system/hp_timer.h>
-#include <util/system/sanitizers.h>
-#include <util/system/thread.h>
-
-Y_UNIT_TEST_SUITE(CpuLoadLog) {
-
- TString PrintBits(ui64 x) {
- TStringStream str;
- for (ui64 i = 0; i < 64; ++i) {
- if (x & (1ull << i)) {
- str << "1";
- } else {
- str << "0";
- }
- }
- return str.Str();
- }
-
- Y_UNIT_TEST(FillAll) {
- TCpuLoadLog<5> log(100*BitDurationNs);
- log.RegisterBusyPeriod(101*BitDurationNs);
- log.RegisterBusyPeriod(163*BitDurationNs);
- log.RegisterBusyPeriod(164*BitDurationNs);
- log.RegisterBusyPeriod(165*BitDurationNs);
- log.RegisterBusyPeriod(331*BitDurationNs);
- log.RegisterBusyPeriod(340*BitDurationNs);
- log.RegisterBusyPeriod(420*BitDurationNs);
- log.RegisterBusyPeriod(511*BitDurationNs);
- //for (ui64 i = 0; i < 5; ++i) {
- // Cerr << "i: " << i << " bits: " << PrintBits(log.Data[i]) << Endl;
- //}
- for (ui64 i = 0; i < 5; ++i) {
- UNIT_ASSERT_C((ui64(log.Data[i]) == ~ui64(0)), "Unequal at " << i << "\n got: " << PrintBits(log.Data[i])
- << "\n expected: " << PrintBits(~ui64(0)));
- }
- }
-
- Y_UNIT_TEST(PartialFill) {
- TCpuLoadLog<5> log(0*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b0ull));
- log.RegisterBusyPeriod(0*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b1ull));
- log.RegisterBusyPeriod(0*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b1ull));
- log.RegisterBusyPeriod(1*BitDurationNs/2);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b1ull));
- log.RegisterBusyPeriod(1*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b11ull));
- log.RegisterIdlePeriod(3*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b11ull));
- log.RegisterBusyPeriod(3*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0b1011ull));
- log.RegisterBusyPeriod(63*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits((~0ull)^0b0100ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0b0ull));
- log.RegisterBusyPeriod(128*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits((~0ull)^0b0100ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0b1ull));
- log.RegisterBusyPeriod(1*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterBusyPeriod(2*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterBusyPeriod(64*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterIdlePeriod(128*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterIdlePeriod(192*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterBusyPeriod(192*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(~0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(~0ull));
- log.RegisterIdlePeriod((192+5*64-1)*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(0b1ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(0ull));
- log.RegisterIdlePeriod((192+15*64)*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[0]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[1]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[2]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[3]), PrintBits(0ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log.Data[4]), PrintBits(0ull));
- }
-
- Y_UNIT_TEST(Estimator) {
- TCpuLoadLog<5> *log[10];
- log[0] = new TCpuLoadLog<5>(0*BitDurationNs);
- log[1] = new TCpuLoadLog<5>(0*BitDurationNs);
- TMinusOneCpuEstimator<5> estimator;
-
-
- for (ui64 i = 0; i < 5*64; i+=2) {
- log[0]->RegisterIdlePeriod(i*BitDurationNs);
- log[0]->RegisterBusyPeriod(i*BitDurationNs);
- }
- log[0]->RegisterIdlePeriod((5*64-2)*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[0]->Data[0]),
- PrintBits(0b0101010101010101010101010101010101010101010101010101010101010101ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[0]->Data[4]),
- PrintBits(0b0101010101010101010101010101010101010101010101010101010101010101ull));
- for (ui64 i = 0; i < 5*64-1; i+=2) {
- log[1]->RegisterIdlePeriod((i+1)*BitDurationNs);
- log[1]->RegisterBusyPeriod((i+1)*BitDurationNs);
- }
- log[1]->RegisterIdlePeriod((5*64-2+1)*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[1]->Data[0]),
- PrintBits(0b1010101010101010101010101010101010101010101010101010101010101010ull));
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[1]->Data[4]),
- PrintBits(0b1010101010101010101010101010101010101010101010101010101010101010ull));
-
- ui64 value = estimator.MaxLatencyIncreaseWithOneLessCpu(log, 2, (5*64)*BitDurationNs-1, 3*64*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(value/BitDurationNs, 1);
-
- value = estimator.MaxLatencyIncreaseWithOneLessCpu(log, 2, (5*64+10)*BitDurationNs, 3*64*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(value/BitDurationNs, 12);
-
- delete log[0];
- delete log[1];
- }
-
- Y_UNIT_TEST(Estimator2) {
- TCpuLoadLog<5> *log[2];
- log[0] = new TCpuLoadLog<5>(0*BitDurationNs);
- log[1] = new TCpuLoadLog<5>(0*BitDurationNs);
- TMinusOneCpuEstimator<5> estimator;
-
- for (ui64 i = 0; i < 5*64; i+=2) {
- log[0]->RegisterIdlePeriod(i*BitDurationNs);
- log[0]->RegisterBusyPeriod(i*BitDurationNs);
- }
- for (ui64 i = 0; i < 5; ++i) {
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[0]->Data[i]),
- PrintBits(0b0101010101010101010101010101010101010101010101010101010101010101ull));
- }
- for (ui64 i = 0; i < 5*64-1; i+=2) {
- log[1]->RegisterIdlePeriod((i+1)*BitDurationNs);
- log[1]->RegisterBusyPeriod((i+1)*BitDurationNs);
- }
- for (ui64 i = 0; i < 5; ++i) {
- UNIT_ASSERT_VALUES_EQUAL(PrintBits(log[1]->Data[i]),
- PrintBits(0b1010101010101010101010101010101010101010101010101010101010101010ull));
- }
-
- log[0]->Data[2] = ~0ull;
- ui64 value = estimator.MaxLatencyIncreaseWithOneLessCpu(log, 2, (5*64-1)*BitDurationNs, 3*64*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(value/BitDurationNs, 32);
-
- delete log[0];
- delete log[1];
- }
-
- Y_UNIT_TEST(Estimator3) {
- TCpuLoadLog<5> *log[3];
- log[0] = new TCpuLoadLog<5>(0*BitDurationNs);
- log[1] = new TCpuLoadLog<5>(0*BitDurationNs);
- log[2] = new TCpuLoadLog<5>(0*BitDurationNs);
- TMinusOneCpuEstimator<5> estimator;
-
- for (ui64 i = 0; i < 5*64; i+=8) {
- log[0]->RegisterIdlePeriod(i*BitDurationNs);
- log[0]->RegisterBusyPeriod((i+3)*BitDurationNs);
- log[1]->RegisterIdlePeriod(i*BitDurationNs);
- log[1]->RegisterBusyPeriod((i+3)*BitDurationNs);
- log[2]->RegisterIdlePeriod(i*BitDurationNs);
- log[2]->RegisterBusyPeriod((i+3)*BitDurationNs);
- }
- for (ui64 i = 0; i < 5; ++i) {
- for (ui64 n = 0; n < 3; ++n) {
- UNIT_ASSERT_VALUES_EQUAL_C(PrintBits(log[n]->Data[i]),
- PrintBits(0b0000111100001111000011110000111100001111000011110000111100001111ull),
- " i: " << i << " n: " << n);
- }
- }
-
- ui64 value = estimator.MaxLatencyIncreaseWithOneLessCpu(log, 3, (5*64-5)*BitDurationNs, 3*64*BitDurationNs);
- UNIT_ASSERT_VALUES_EQUAL(value/BitDurationNs, 4);
-
- delete log[0];
- delete log[1];
- delete log[2];
- }
- /*
- class TWorkerThread : public ISimpleThread {
- private:
- std::function<void()> Func;
- double Time = 0.0;
-
- public:
- TWorkerThread(std::function<void()> func)
- : Func(std::move(func))
- { }
-
- double GetTime() const {
- return Time;
- }
-
- static THolder<TWorkerThread> Spawn(std::function<void()> func) {
- THolder<TWorkerThread> thread = MakeHolder<TWorkerThread>(std::move(func));
- thread->Start();
- return thread;
- }
-
- private:
- void* ThreadProc() noexcept override {
- THPTimer timer;
- Func();
- Time = timer.Passed();
- return nullptr;
- }
- };
-
- void DoConcurrentPushPop(size_t threads, ui64 perThreadCount) {
- // Concurrency factor 4 is up to 16 threads
-
- auto workerFunc = [&](size_t threadIndex) {
- };
-
- TVector<THolder<TWorkerThread>> workers(threads);
- for (size_t i = 0; i < threads; ++i) {
- workers[i] = TWorkerThread::Spawn([workerFunc, i]() {
- workerFunc(i);
- });
- }
-
- double maxTime = 0;
- for (size_t i = 0; i < threads; ++i) {
- workers[i]->Join();
- maxTime = Max(maxTime, workers[i]->GetTime());
- }
-
- UNIT_ASSERT_VALUES_EQUAL(popped, 0u);
-
- Cerr << "Concurrent with " << threads << " threads: " << maxTime << " seconds" << Endl;
- }
-
- void DoConcurrentPushPop_3times(size_t threads, ui64 perThreadCount) {
- for (size_t i = 0; i < 3; ++i) {
- DoConcurrentPushPop(threads, perThreadCount);
- }
- }
-
- static constexpr ui64 PER_THREAD_COUNT = NSan::PlainOrUnderSanitizer(1000000, 100000);
-
- Y_UNIT_TEST(ConcurrentPushPop_1thread) { DoConcurrentPushPop_3times(1, PER_THREAD_COUNT); }
- */
-}
diff --git a/library/cpp/actors/util/cpumask.h b/library/cpp/actors/util/cpumask.h
deleted file mode 100644
index 29741aa1d6..0000000000
--- a/library/cpp/actors/util/cpumask.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#pragma once
-
-#include "defs.h"
-
-#include <library/cpp/containers/stack_vector/stack_vec.h>
-
-#include <util/string/split.h>
-#include <util/generic/yexception.h>
-
-using TCpuId = ui32;
-
-// Simple data structure to operate with set of cpus
-struct TCpuMask {
- TStackVec<bool, 1024> Cpus;
-
- // Creates empty mask
- TCpuMask() {}
-
- // Creates mask with single cpu set
- explicit TCpuMask(TCpuId cpuId) {
- Set(cpuId);
- }
-
- // Initialize mask from raw boolean array
- template <class T>
- TCpuMask(const T* cpus, TCpuId size) {
- Cpus.reserve(size);
- for (TCpuId i = 0; i != size; ++i) {
- Cpus.emplace_back(bool(cpus[i]));
- }
- }
-
- // Parse a numerical list of processors. The numbers are separated by commas and may include ranges. For example: 0,5,7,9-11
- explicit TCpuMask(const TString& cpuList) {
- try {
- for (TStringBuf s : StringSplitter(cpuList).Split(',')) {
- TCpuId l, r;
- if (s.find('-') != TString::npos) {
- StringSplitter(s).Split('-').CollectInto(&l, &r);
- } else {
- l = r = FromString<TCpuId>(s);
- }
- if (r >= Cpus.size()) {
- Cpus.resize(r + 1, false);
- }
- for (TCpuId cpu = l; cpu <= r; cpu++) {
- Cpus[cpu] = true;
- }
- }
- } catch (...) {
- ythrow TWithBackTrace<yexception>() << "Exception occured while parsing cpu list '" << cpuList << "': " << CurrentExceptionMessage();
- }
- }
-
- // Returns size of underlying vector
- TCpuId Size() const {
- return Cpus.size();
- }
-
- // Returns number of set bits in mask
- TCpuId CpuCount() const {
- TCpuId result = 0;
- for (bool value : Cpus) {
- result += value;
- }
- return result;
- }
-
- bool IsEmpty() const {
- for (bool value : Cpus) {
- if (value) {
- return false;
- }
- }
- return true;
- }
-
- bool IsSet(TCpuId cpu) const {
- return cpu < Cpus.size() && Cpus[cpu];
- }
-
- void Set(TCpuId cpu) {
- if (cpu >= Cpus.size()) {
- Cpus.resize(cpu + 1, false);
- }
- Cpus[cpu] = true;
- }
-
- void Reset(TCpuId cpu) {
- if (cpu < Cpus.size()) {
- Cpus[cpu] = false;
- }
- }
-
- void RemoveTrailingZeros() {
- while (!Cpus.empty() && !Cpus.back()) {
- Cpus.pop_back();
- }
- }
-
- explicit operator bool() const {
- return !IsEmpty();
- }
-
- TCpuMask operator &(const TCpuMask& rhs) const {
- TCpuMask result;
- TCpuId size = Max(Size(), rhs.Size());
- result.Cpus.reserve(size);
- for (TCpuId cpu = 0; cpu < size; cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) && rhs.IsSet(cpu));
- }
- return result;
- }
-
- TCpuMask operator |(const TCpuMask& rhs) const {
- TCpuMask result;
- TCpuId size = Max(Size(), rhs.Size());
- result.Cpus.reserve(size);
- for (TCpuId cpu = 0; cpu < size; cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) || rhs.IsSet(cpu));
- }
- return result;
- }
-
- TCpuMask operator -(const TCpuMask& rhs) const {
- TCpuMask result;
- result.Cpus.reserve(Size());
- for (TCpuId cpu = 0; cpu < Size(); cpu++) {
- result.Cpus.emplace_back(IsSet(cpu) && !rhs.IsSet(cpu));
- }
- return result;
- }
-};
diff --git a/library/cpp/actors/util/datetime.h b/library/cpp/actors/util/datetime.h
deleted file mode 100644
index cbec5965d6..0000000000
--- a/library/cpp/actors/util/datetime.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include <util/system/defaults.h>
-#include <util/system/hp_timer.h>
-#include <util/system/platform.h>
-
-#if defined(_win_)
-#include <intrin.h>
-#pragma intrinsic(__rdtsc)
-#endif // _win_
-
-#if defined(_darwin_) && !defined(_x86_)
-#include <mach/mach_time.h>
-#endif
-
-// GetCycleCount() from util/system/datetime.h uses rdtscp, which is more accurate than rdtsc,
-// but rdtscp disables processor's out-of-order execution, so it can be slow
-Y_FORCE_INLINE ui64 GetCycleCountFast() {
-#if defined(_MSC_VER)
- // Generates the rdtsc instruction, which returns the processor time stamp.
- // The processor time stamp records the number of clock cycles since the last reset.
- return __rdtsc();
-#elif defined(__clang__) && !defined(_arm64_)
- return __builtin_readcyclecounter();
-#elif defined(_x86_64_)
- unsigned hi, lo;
- __asm__ __volatile__("rdtsc"
- : "=a"(lo), "=d"(hi));
- return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
-#elif defined(_i386_)
- ui64 x;
- __asm__ volatile("rdtsc\n\t"
- : "=A"(x));
- return x;
-#elif defined(_darwin_)
- return mach_absolute_time();
-#elif defined(_arm32_)
- return MicroSeconds();
-#elif defined(_arm64_)
- ui64 x;
-
- __asm__ __volatile__("isb; mrs %0, cntvct_el0"
- : "=r"(x));
-
- return x;
-#else
-#error "unsupported arch"
-#endif
-}
-
-// NHPTimer::GetTime fast analog
-Y_FORCE_INLINE void GetTimeFast(NHPTimer::STime* pTime) noexcept {
- *pTime = GetCycleCountFast();
-}
-
-namespace NActors {
- inline double Ts2Ns(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e9;
- }
-
- inline double Ts2Us(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e6;
- }
-
- inline double Ts2Ms(ui64 ts) {
- return NHPTimer::GetSeconds(ts) * 1e3;
- }
-
- inline ui64 Us2Ts(double us) {
- return ui64(NHPTimer::GetClockRate() * us / 1e6);
- }
-
- struct TTimeTracker {
- ui64 Ts;
- TTimeTracker(): Ts(GetCycleCountFast()) {}
- ui64 Elapsed() {
- ui64 ts = GetCycleCountFast();
- std::swap(Ts, ts);
- return Ts - ts;
- }
- };
-}
diff --git a/library/cpp/actors/util/defs.h b/library/cpp/actors/util/defs.h
deleted file mode 100644
index 70f969753e..0000000000
--- a/library/cpp/actors/util/defs.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-// unique tag to fix pragma once gcc glueing: ./library/actors/util/defs.h
-
-#include <util/system/defaults.h>
-#include <util/generic/bt_exception.h>
-#include <util/generic/noncopyable.h>
-#include <util/generic/ptr.h>
-#include <util/generic/string.h>
-#include <util/generic/yexception.h>
-#include <library/cpp/deprecated/atomic/atomic.h>
-#include <util/system/align.h>
-#include <util/generic/vector.h>
-#include <util/datetime/base.h>
-#include <util/generic/ylimits.h>
-#include "intrinsics.h"
diff --git a/library/cpp/actors/util/funnel_queue.h b/library/cpp/actors/util/funnel_queue.h
deleted file mode 100644
index 15af57b121..0000000000
--- a/library/cpp/actors/util/funnel_queue.h
+++ /dev/null
@@ -1,240 +0,0 @@
-#pragma once
-
-#include <library/cpp/deprecated/atomic/atomic.h>
-#include <util/generic/noncopyable.h>
-
-template <typename ElementType>
-class TFunnelQueue: private TNonCopyable {
-public:
- TFunnelQueue() noexcept
- : Front(nullptr)
- , Back(nullptr)
- {
- }
-
- virtual ~TFunnelQueue() noexcept {
- for (auto entry = Front; entry; entry = DeleteEntry(entry))
- continue;
- }
-
- /// Push element. Can be used from many threads. Return true if is first element.
- bool
- Push(ElementType&& element) noexcept {
- TEntry* const next = NewEntry(static_cast<ElementType&&>(element));
- TEntry* const prev = AtomicSwap(&Back, next);
- AtomicSet(prev ? prev->Next : Front, next);
- return !prev;
- }
-
- /// Extract top element. Must be used only from one thread. Return true if have more.
- bool
- Pop() noexcept {
- if (TEntry* const top = AtomicGet(Front)) {
- const auto last = AtomicCas(&Back, nullptr, top);
- if (last) // This is last element in queue. Queue is empty now.
- AtomicCas(&Front, nullptr, top);
- else // This element is not last.
- for (;;) {
- if (const auto next = AtomicGet(top->Next)) {
- AtomicSet(Front, next);
- break;
- }
- // But Next is null. Wait next assignment in spin lock.
- }
-
- DeleteEntry(top);
- return !last;
- }
-
- return false;
- }
-
- /// Peek top element. Must be used only from one thread.
- ElementType&
- Top() const noexcept {
- return AtomicGet(Front)->Data;
- }
-
- bool
- IsEmpty() const noexcept {
- return !AtomicGet(Front);
- }
-
-protected:
- class TEntry: private TNonCopyable {
- friend class TFunnelQueue;
-
- private:
- explicit TEntry(ElementType&& element) noexcept
- : Data(static_cast<ElementType&&>(element))
- , Next(nullptr)
- {
- }
-
- ~TEntry() noexcept {
- }
-
- public:
- ElementType Data;
- TEntry* volatile Next;
- };
-
- TEntry* volatile Front;
- TEntry* volatile Back;
-
- virtual TEntry* NewEntry(ElementType&& element) noexcept {
- return new TEntry(static_cast<ElementType&&>(element));
- }
-
- virtual TEntry* DeleteEntry(TEntry* entry) noexcept {
- const auto next = entry->Next;
- delete entry;
- return next;
- }
-
-protected:
- struct TEntryIter {
- TEntry* ptr;
-
- ElementType& operator*() {
- return ptr->Data;
- }
-
- ElementType* operator->() {
- return &ptr->Data;
- }
-
- TEntryIter& operator++() {
- ptr = AtomicGet(ptr->Next);
- return *this;
- }
-
- bool operator!=(const TEntryIter& other) const {
- return ptr != other.ptr;
- }
-
- bool operator==(const TEntryIter& other) const {
- return ptr == other.ptr;
- }
- };
-
- struct TConstEntryIter {
- const TEntry* ptr;
-
- const ElementType& operator*() {
- return ptr->Data;
- }
-
- const ElementType* operator->() {
- return &ptr->Data;
- }
-
- TEntryIter& operator++() {
- ptr = AtomicGet(ptr->Next);
- return *this;
- }
-
- bool operator!=(const TConstEntryIter& other) const {
- return ptr != other.ptr;
- }
-
- bool operator==(const TConstEntryIter& other) const {
- return ptr == other.ptr;
- }
- };
-
-public:
- using const_iterator = TConstEntryIter;
- using iterator = TEntryIter;
-
- iterator begin() {
- return {AtomicGet(Front)};
- }
- const_iterator cbegin() {
- return {AtomicGet(Front)};
- }
- const_iterator begin() const {
- return {AtomicGet(Front)};
- }
-
- iterator end() {
- return {nullptr};
- }
- const_iterator cend() {
- return {nullptr};
- }
- const_iterator end() const {
- return {nullptr};
- }
-};
-
-template <typename ElementType>
-class TPooledFunnelQueue: public TFunnelQueue<ElementType> {
-public:
- TPooledFunnelQueue() noexcept
- : Stack(nullptr)
- {
- }
-
- virtual ~TPooledFunnelQueue() noexcept override {
- for (auto entry = TBase::Front; entry; entry = TBase::DeleteEntry(entry))
- continue;
- for (auto entry = Stack; entry; entry = TBase::DeleteEntry(entry))
- continue;
- TBase::Back = TBase::Front = Stack = nullptr;
- }
-
-private:
- typedef TFunnelQueue<ElementType> TBase;
-
- typename TBase::TEntry* volatile Stack;
-
-protected:
- virtual typename TBase::TEntry* NewEntry(ElementType&& element) noexcept override {
- while (const auto top = AtomicGet(Stack))
- if (AtomicCas(&Stack, top->Next, top)) {
- top->Data = static_cast<ElementType&&>(element);
- AtomicSet(top->Next, nullptr);
- return top;
- }
-
- return TBase::NewEntry(static_cast<ElementType&&>(element));
- }
-
- virtual typename TBase::TEntry* DeleteEntry(typename TBase::TEntry* entry) noexcept override {
- entry->Data = ElementType();
- const auto next = entry->Next;
- do
- AtomicSet(entry->Next, AtomicGet(Stack));
- while (!AtomicCas(&Stack, entry, entry->Next));
- return next;
- }
-};
-
-template <typename ElementType, template <typename T> class TQueueType = TFunnelQueue>
-class TCountedFunnelQueue: public TQueueType<ElementType> {
-public:
- TCountedFunnelQueue() noexcept
- : Count(0)
- {
- }
-
- TAtomicBase GetSize() const noexcept {
- return AtomicGet(Count);
- }
-
-private:
- typedef TQueueType<ElementType> TBase;
-
- virtual typename TBase::TEntry* NewEntry(ElementType&& element) noexcept override {
- AtomicAdd(Count, 1);
- return TBase::NewEntry(static_cast<ElementType&&>(element));
- }
-
- virtual typename TBase::TEntry* DeleteEntry(typename TBase::TEntry* entry) noexcept override {
- AtomicSub(Count, 1);
- return TBase::DeleteEntry(entry);
- }
-
- TAtomic Count;
-};
diff --git a/library/cpp/actors/util/futex.h b/library/cpp/actors/util/futex.h
deleted file mode 100644
index c193f8d128..0000000000
--- a/library/cpp/actors/util/futex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#ifdef _linux_
-
-#include <linux/futex.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-
-static long SysFutex(void* addr1, int op, int val1, struct timespec* timeout, void* addr2, int val3) {
- return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
-}
-
-#endif
diff --git a/library/cpp/actors/util/intrinsics.h b/library/cpp/actors/util/intrinsics.h
deleted file mode 100644
index c02b633b70..0000000000
--- a/library/cpp/actors/util/intrinsics.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#pragma once
-
-#include <util/system/defaults.h>
-#include <library/cpp/deprecated/atomic/atomic.h>
-#include <util/system/spinlock.h>
-
-#include <library/cpp/sse/sse.h> // The header chooses appropriate SSE support
-
-static_assert(sizeof(TAtomic) == 8, "expect sizeof(TAtomic) == 8");
-
-// we need explicit 32 bit operations to keep cache-line friendly packs
-// so have to define some atomics additionaly to arcadia one
-#ifdef _win_
-#pragma intrinsic(_InterlockedCompareExchange)
-#pragma intrinsic(_InterlockedExchangeAdd)
-#pragma intrinsic(_InterlockedIncrement)
-#pragma intrinsic(_InterlockedDecrement)
-#endif
-
-inline bool AtomicUi32Cas(volatile ui32* a, ui32 exchange, ui32 compare) {
-#ifdef _win_
- return _InterlockedCompareExchange((volatile long*)a, exchange, compare) == (long)compare;
-#else
- ui32 expected = compare;
- return __atomic_compare_exchange_n(a, &expected, exchange, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
-#endif
-}
-
-inline ui32 AtomicUi32Add(volatile ui32* a, ui32 add) {
-#ifdef _win_
- return _InterlockedExchangeAdd((volatile long*)a, add) + add;
-#else
- return __atomic_add_fetch(a, add, __ATOMIC_SEQ_CST);
-#endif
-}
-
-inline ui32 AtomicUi32Sub(volatile ui32* a, ui32 sub) {
-#ifdef _win_
- return _InterlockedExchangeAdd((volatile long*)a, -(long)sub) - sub;
-#else
- return __atomic_sub_fetch(a, sub, __ATOMIC_SEQ_CST);
-#endif
-}
-
-inline ui32 AtomicUi32Increment(volatile ui32* a) {
-#ifdef _win_
- return _InterlockedIncrement((volatile long*)a);
-#else
- return __atomic_add_fetch(a, 1, __ATOMIC_SEQ_CST);
-#endif
-}
-
-inline ui32 AtomicUi32Decrement(volatile ui32* a) {
-#ifdef _win_
- return _InterlockedDecrement((volatile long*)a);
-#else
- return __atomic_sub_fetch(a, 1, __ATOMIC_SEQ_CST);
-#endif
-}
-
-template <typename T>
-inline void AtomicStore(volatile T* a, T x) {
- static_assert(std::is_integral<T>::value || std::is_pointer<T>::value, "expect std::is_integral<T>::value || std::is_pointer<T>::value");
-#ifdef _win_
- *a = x;
-#else
- __atomic_store_n(a, x, __ATOMIC_RELEASE);
-#endif
-}
-
-template <typename T>
-inline void RelaxedStore(volatile T* a, T x) {
- static_assert(std::is_integral<T>::value || std::is_pointer<T>::value, "expect std::is_integral<T>::value || std::is_pointer<T>::value");
-#ifdef _win_
- *a = x;
-#else
- __atomic_store_n(a, x, __ATOMIC_RELAXED);
-#endif
-}
-
-template <typename T>
-inline T AtomicLoad(volatile T* a) {
-#ifdef _win_
- return *a;
-#else
- return __atomic_load_n(a, __ATOMIC_ACQUIRE);
-#endif
-}
-
-template <typename T>
-inline T RelaxedLoad(volatile T* a) {
-#ifdef _win_
- return *a;
-#else
- return __atomic_load_n(a, __ATOMIC_RELAXED);
-#endif
-}
diff --git a/library/cpp/actors/util/local_process_key.h b/library/cpp/actors/util/local_process_key.h
deleted file mode 100644
index bff8bef81b..0000000000
--- a/library/cpp/actors/util/local_process_key.h
+++ /dev/null
@@ -1,157 +0,0 @@
-#pragma once
-
-#include <util/string/builder.h>
-#include <util/system/mutex.h>
-#include <util/generic/strbuf.h>
-#include <util/generic/vector.h>
-#include <util/generic/hash.h>
-#include <util/generic/singleton.h>
-#include <util/generic/serialized_enum.h>
-
-class TLocalProcessKeyStateIndexLimiter {
-public:
- static constexpr ui32 GetMaxKeysCount() {
- return 10000;
- }
-};
-
-template <class T>
-class TLocalProcessKeyStateIndexConstructor {
-public:
-};
-
-template <typename T>
-class TLocalProcessKeyState {
-
-template <typename U, const char* Name>
-friend class TLocalProcessKey;
-template <typename U, class TClass, ui32 KeyLengthLimit>
-friend class TLocalProcessExtKey;
-template <typename U, typename EnumT>
-friend class TEnumProcessKey;
-
-public:
- static TLocalProcessKeyState& GetInstance() {
- return *Singleton<TLocalProcessKeyState<T>>();
- }
-
- ui32 GetCount() const {
- return MaxKeysCount;
- }
-
- TStringBuf GetNameByIndex(size_t index) const {
- Y_ABORT_UNLESS(index < Names.size());
- return Names[index];
- }
-
- size_t GetIndexByName(TStringBuf name) const {
- TGuard<TMutex> g(Mutex);
- auto it = Map.find(name);
- Y_ENSURE(it != Map.end());
- return it->second;
- }
-
- TLocalProcessKeyState() {
- Names.resize(MaxKeysCount);
- }
-
- size_t Register(TStringBuf name) {
- TGuard<TMutex> g(Mutex);
- auto it = Map.find(name);
- if (it != Map.end()) {
- return it->second;
- }
- const ui32 index = TLocalProcessKeyStateIndexConstructor<T>::BuildCurrentIndex(name, Names.size());
- auto x = Map.emplace(name, index);
- if (x.second) {
- Y_ABORT_UNLESS(index < Names.size(), "a lot of actors or tags for memory monitoring");
- Names[index] = name;
- }
-
- return x.first->second;
- }
-
-private:
-
- static constexpr ui32 MaxKeysCount = TLocalProcessKeyStateIndexLimiter::GetMaxKeysCount();
-
-private:
- TVector<TString> Names;
- THashMap<TString, size_t> Map;
- TMutex Mutex;
-};
-
-template <typename T, const char* Name>
-class TLocalProcessKey {
-public:
- static TStringBuf GetName() {
- return Name;
- }
-
- static size_t GetIndex() {
- return Index;
- }
-
-private:
- inline static size_t Index = TLocalProcessKeyState<T>::GetInstance().Register(Name);
-};
-
-template <typename T, class TClass, ui32 KeyLengthLimit = 0>
-class TLocalProcessExtKey {
-public:
- static TStringBuf GetName() {
- return Name;
- }
-
- static size_t GetIndex() {
- return Index;
- }
-
-private:
-
- static TString TypeNameRobust() {
- const TString className = TypeName<TClass>();
- if (KeyLengthLimit && className.size() > KeyLengthLimit) {
- return className.substr(0, KeyLengthLimit - 3) + "...";
- } else {
- return className;
- }
- }
-
- static const inline TString Name = TypeName<TClass>();
- inline static size_t Index = TLocalProcessKeyState<T>::GetInstance().Register(TypeNameRobust());
-};
-
-template <typename T, typename EnumT>
-class TEnumProcessKey {
-public:
- static TStringBuf GetName(const EnumT key) {
- return TLocalProcessKeyState<T>::GetInstance().GetNameByIndex(GetIndex(key));
- }
-
- static size_t GetIndex(const EnumT key) {
- ui32 index = static_cast<ui32>(key);
- Y_ABORT_UNLESS(index < Enum2Index.size());
- return Enum2Index[index];
- }
-
-private:
- inline static TVector<size_t> RegisterAll() {
- static_assert(std::is_enum<EnumT>::value, "Enum is required");
-
- TVector<size_t> enum2Index;
- auto names = GetEnumNames<EnumT>();
- ui32 maxId = 0;
- for (const auto& [k, v] : names) {
- maxId = Max(maxId, static_cast<ui32>(k));
- }
- enum2Index.resize(maxId + 1);
- for (const auto& [k, v] : names) {
- ui32 enumId = static_cast<ui32>(k);
- enum2Index[enumId] = TLocalProcessKeyState<T>::GetInstance().Register(v);
- }
- return enum2Index;
- }
-
- inline static TVector<size_t> Enum2Index = RegisterAll();
-};
diff --git a/library/cpp/actors/util/memory_track.cpp b/library/cpp/actors/util/memory_track.cpp
deleted file mode 100644
index 5f422116be..0000000000
--- a/library/cpp/actors/util/memory_track.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "memory_track.h"
-#include "memory_tracker.h"
-
-namespace NActors {
-namespace NMemory {
-
-namespace NPrivate {
-
-TThreadLocalInfo::TThreadLocalInfo()
- : Metrics(TMemoryTracker::Instance()->GetCount())
-{
- TMemoryTracker::Instance()->OnCreateThread(this);
-}
-
-TThreadLocalInfo::~TThreadLocalInfo() {
- TMemoryTracker::Instance()->OnDestroyThread(this);
-}
-
-TMetric* TThreadLocalInfo::GetMetric(size_t index) {
- if (Y_UNLIKELY(index >= Metrics.size())) {
- return &Null;
- }
- return &Metrics[index];
-}
-
-const std::vector<TMetric>& TThreadLocalInfo::GetMetrics() const {
- return Metrics;
-}
-
-size_t TBaseLabel::RegisterStaticMemoryLabel(const char* name, bool hasSensor) {
- return TMemoryTracker::Instance()->RegisterStaticMemoryLabel(name, hasSensor);
-}
-
-}
-
-}
-}
-
diff --git a/library/cpp/actors/util/memory_track.h b/library/cpp/actors/util/memory_track.h
deleted file mode 100644
index 6035333eeb..0000000000
--- a/library/cpp/actors/util/memory_track.h
+++ /dev/null
@@ -1,293 +0,0 @@
-#pragma once
-
-#include <vector>
-
-#include <util/system/type_name.h>
-#include <util/thread/singleton.h>
-
-#define ENABLE_MEMORY_TRACKING
-
-namespace NActors {
-namespace NMemory {
-
-namespace NPrivate {
-
-class TMetric {
- std::atomic<ssize_t> Memory;
- std::atomic<ssize_t> Count;
-
- void Copy(const TMetric& other) {
- Memory.store(other.GetMemory(), std::memory_order_relaxed);
- Count.store(other.GetCount(), std::memory_order_relaxed);
- }
-
-public:
- TMetric()
- : Memory(0)
- , Count(0)
- {}
-
- inline TMetric(const TMetric& other) {
- Copy(other);
- }
-
- inline TMetric(TMetric&& other) {
- Copy(other);
- }
-
- inline TMetric& operator=(const TMetric& other) {
- Copy(other);
- return *this;
- }
-
- inline TMetric& operator=(TMetric&& other) {
- Copy(other);
- return *this;
- }
-
- inline ssize_t GetMemory() const {
- return Memory.load(std::memory_order_relaxed);
- }
- inline void SetMemory(ssize_t value) {
- Memory.store(value, std::memory_order_relaxed);
- }
-
- inline ssize_t GetCount() const {
- return Count.load(std::memory_order_relaxed);
- }
- inline void SetCount(ssize_t value) {
- Count.store(value, std::memory_order_relaxed);
- }
-
- inline void operator+=(const TMetric& other) {
- SetMemory(GetMemory() + other.GetMemory());
- SetCount(GetCount() + other.GetCount());
- }
-
- inline void CalculatePeak(const TMetric& other) {
- SetMemory(Max(GetMemory(), other.GetMemory()));
- SetCount(Max(GetCount(), other.GetCount()));
- }
-
- inline void Add(size_t size) {
- SetMemory(GetMemory() + size);
- SetCount(GetCount() + 1);
- }
-
- inline void Sub(size_t size) {
- SetMemory(GetMemory() - size);
- SetCount(GetCount() - 1);
- }
-};
-
-
-class TThreadLocalInfo {
-public:
- TThreadLocalInfo();
- ~TThreadLocalInfo();
-
- TMetric* GetMetric(size_t index);
- const std::vector<TMetric>& GetMetrics() const;
-
-private:
- std::vector<TMetric> Metrics;
-
- inline static TMetric Null = {};
-};
-
-
-class TBaseLabel {
-protected:
- static size_t RegisterStaticMemoryLabel(const char* name, bool hasSensor);
-
- inline static TMetric* GetLocalMetric(size_t index) {
- return FastTlsSingleton<TThreadLocalInfo>()->GetMetric(index);
- }
-};
-
-
-template <const char* Name>
-class TNameLabel
- : TBaseLabel
-{
-public:
- static void Add(size_t size) {
-#if defined(ENABLE_MEMORY_TRACKING)
- Y_UNUSED(MetricInit);
-
- if (Y_UNLIKELY(!Metric)) {
- Metric = GetLocalMetric(Index);
- }
-
- Metric->Add(size);
-#else
- Y_UNUSED(size);
-#endif
- }
-
- static void Sub(size_t size) {
-#if defined(ENABLE_MEMORY_TRACKING)
- Y_UNUSED(MetricInit);
-
- if (Y_UNLIKELY(!Metric)) {
- Metric = GetLocalMetric(Index);
- }
-
- Metric->Sub(size);
-#else
- Y_UNUSED(size);
-#endif
- }
-
-private:
-#if defined(ENABLE_MEMORY_TRACKING)
- inline static size_t Index = Max<size_t>();
- inline static struct TMetricInit {
- TMetricInit() {
- Index = RegisterStaticMemoryLabel(Name, true);
- }
- } MetricInit;
-
- inline static thread_local TMetric* Metric = nullptr;
-#endif
-};
-
-
-template <typename TType>
-class TTypeLabel
- : TBaseLabel
-{
-public:
- static void Add(size_t size) {
-#if defined(ENABLE_MEMORY_TRACKING)
- Y_UNUSED(MetricInit);
-
- if (Y_UNLIKELY(!Metric)) {
- Metric = GetLocalMetric(Index);
- }
-
- Metric->Add(size);
-#else
- Y_UNUSED(size);
-#endif
- }
-
- static void Sub(size_t size) {
-#if defined(ENABLE_MEMORY_TRACKING)
- Y_UNUSED(MetricInit);
-
- if (Y_UNLIKELY(!Metric)) {
- Metric = GetLocalMetric(Index);
- }
-
- Metric->Sub(size);
-#else
- Y_UNUSED(size);
-#endif
- }
-
-private:
-#if defined(ENABLE_MEMORY_TRACKING)
- inline static size_t Index = Max<size_t>();
- inline static struct TMetricInit {
- TMetricInit() {
- Index = RegisterStaticMemoryLabel(TypeName<TType>().c_str(), false);
- }
- } MetricInit;
-
- inline static thread_local TMetric* Metric = nullptr;
-#endif
-};
-
-
-template <typename T>
-struct TTrackHelper {
-#if defined(ENABLE_MEMORY_TRACKING)
- void* operator new(size_t size) {
- T::Add(size);
- return malloc(size);
- }
-
- void* operator new[](size_t size) {
- T::Add(size);
- return malloc(size);
- }
-
- void operator delete(void* ptr, size_t size) {
- T::Sub(size);
- free(ptr);
- }
-
- void operator delete[](void* ptr, size_t size) {
- T::Sub(size);
- free(ptr);
- }
-#endif
-};
-
-template <typename TType, typename T>
-struct TAllocHelper {
- typedef size_t size_type;
- typedef TType value_type;
- typedef TType* pointer;
- typedef const TType* const_pointer;
-
- struct propagate_on_container_copy_assignment : public std::false_type {};
- struct propagate_on_container_move_assignment : public std::false_type {};
- struct propagate_on_container_swap : public std::false_type {};
-
- pointer allocate(size_type n, const void* hint = nullptr) {
- Y_UNUSED(hint);
- auto size = n * sizeof(TType);
- T::Add(size);
- return (pointer)malloc(size);
- }
-
- void deallocate(pointer ptr, size_t n) {
- auto size = n * sizeof(TType);
- T::Sub(size);
- free((void*)ptr);
- }
-};
-
-} // NPrivate
-
-
-template <const char* Name>
-using TLabel = NPrivate::TNameLabel<Name>;
-
-template <typename TType, const char* Name = nullptr>
-struct TTrack
- : public NPrivate::TTrackHelper<NPrivate::TNameLabel<Name>>
-{
-};
-
-template <typename TType>
-struct TTrack<TType, nullptr>
- : public NPrivate::TTrackHelper<NPrivate::TTypeLabel<TType>>
-{
-};
-
-template <typename TType, const char* Name = nullptr>
-struct TAlloc
- : public NPrivate::TAllocHelper<TType, NPrivate::TNameLabel<Name>>
-{
- template<typename U>
- struct rebind {
- typedef TAlloc<U, Name> other;
- };
-};
-
-template <typename TType>
-struct TAlloc<TType, nullptr>
- : public NPrivate::TAllocHelper<TType, NPrivate::TTypeLabel<TType>>
-{
- template<typename U>
- struct rebind {
- typedef TAlloc<U> other;
- };
-};
-
-}
-}
-
diff --git a/library/cpp/actors/util/memory_tracker.cpp b/library/cpp/actors/util/memory_tracker.cpp
deleted file mode 100644
index 8a12452c71..0000000000
--- a/library/cpp/actors/util/memory_tracker.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "memory_tracker.h"
-
-#include <util/generic/xrange.h>
-
-namespace NActors {
-namespace NMemory {
-
-namespace NPrivate {
-
-TMemoryTracker* TMemoryTracker::Instance() {
- return SingletonWithPriority<TMemoryTracker, 0>();
-}
-
-void TMemoryTracker::Initialize() {
- GlobalMetrics.resize(Indices.size());
-}
-
-const std::map<TString, size_t>& TMemoryTracker::GetMetricIndices() const {
- return Indices;
-}
-
-const std::unordered_set<size_t>& TMemoryTracker::GetSensors() const {
- return Sensors;
-}
-
-TString TMemoryTracker::GetName(size_t index) const {
- return Names[index];
-}
-
-size_t TMemoryTracker::GetCount() const {
- return Indices.size();
-}
-
-void TMemoryTracker::GatherMetrics(std::vector<TMetric>& metrics) const {
- metrics.resize(0);
- auto count = GetCount();
-
- if (!count || GlobalMetrics.size() != count) {
- return;
- }
-
- TReadGuard guard(LockThreadInfo);
-
- metrics.resize(count);
- for (size_t i : xrange(count)) {
- metrics[i] += GlobalMetrics[i];
- }
-
- for (auto info : ThreadInfo) {
- auto& localMetrics = info->GetMetrics();
- if (localMetrics.size() == count) {
- for (size_t i : xrange(count)) {
- metrics[i] += localMetrics[i];
- }
- }
- }
-}
-
-size_t TMemoryTracker::RegisterStaticMemoryLabel(const char* name, bool hasSensor) {
- size_t index = 0;
- auto found = Indices.find(name);
- if (found == Indices.end()) {
- TString str(name);
- auto next = Names.size();
- Indices.emplace(str, next);
- Names.push_back(str);
- index = next;
- } else {
- index = found->second;
- }
-
- if (hasSensor) {
- Sensors.emplace(index);
- }
- return index;
-}
-
-void TMemoryTracker::OnCreateThread(TThreadLocalInfo* info) {
- TWriteGuard guard(LockThreadInfo);
- ThreadInfo.insert(info);
-}
-
-void TMemoryTracker::OnDestroyThread(TThreadLocalInfo* info) {
- TWriteGuard guard(LockThreadInfo);
-
- auto count = GetCount();
- if (count && GlobalMetrics.size() == count) {
- const auto& localMetrics = info->GetMetrics();
- if (localMetrics.size() == count) {
- for (size_t i : xrange(count)) {
- GlobalMetrics[i] += localMetrics[i];
- }
- }
- }
-
- ThreadInfo.erase(info);
-}
-
-}
-
-}
-}
-
diff --git a/library/cpp/actors/util/memory_tracker.h b/library/cpp/actors/util/memory_tracker.h
deleted file mode 100644
index e74508191b..0000000000
--- a/library/cpp/actors/util/memory_tracker.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include "memory_track.h"
-
-#include <map>
-#include <unordered_map>
-#include <unordered_set>
-
-#include <util/system/rwlock.h>
-
-namespace NActors {
-namespace NMemory {
-
-namespace NPrivate {
-
-class TMemoryTracker {
-public:
- static TMemoryTracker* Instance();
-
- void Initialize();
-
- const std::map<TString, size_t>& GetMetricIndices() const;
- const std::unordered_set<size_t>& GetSensors() const;
- TString GetName(size_t index) const;
- size_t GetCount() const;
-
- void GatherMetrics(std::vector<TMetric>& metrics) const;
-
-private:
- size_t RegisterStaticMemoryLabel(const char* name, bool hasSensor);
-
- void OnCreateThread(TThreadLocalInfo* info);
- void OnDestroyThread(TThreadLocalInfo* info);
-
-private:
- std::map<TString, size_t> Indices;
- std::vector<TString> Names;
-
- std::vector<TMetric> GlobalMetrics;
-
- std::unordered_set<size_t> Sensors;
-
- std::unordered_set<TThreadLocalInfo*> ThreadInfo;
- TRWMutex LockThreadInfo;
-
- friend class TThreadLocalInfo;
- friend class TBaseLabel;
-};
-
-}
-
-}
-}
diff --git a/library/cpp/actors/util/memory_tracker_ut.cpp b/library/cpp/actors/util/memory_tracker_ut.cpp
deleted file mode 100644
index 1b8eff7cc5..0000000000
--- a/library/cpp/actors/util/memory_tracker_ut.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-#include "memory_tracker.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-
-#include <util/system/hp_timer.h>
-#include <util/system/thread.h>
-
-namespace NActors {
-namespace NMemory {
-
-Y_UNIT_TEST_SUITE(TMemoryTrackerTest) {
-
-#if defined(ENABLE_MEMORY_TRACKING)
-
-using namespace NPrivate;
-
-size_t FindLabelIndex(const char* label) {
- auto indices = TMemoryTracker::Instance()->GetMetricIndices();
- auto it = indices.find(label);
- UNIT_ASSERT(it != indices.end());
- return it->second;
-}
-
-
-struct TTypeLabeled
- : public NActors::NMemory::TTrack<TTypeLabeled>
-{
- char payload[16];
-};
-
-static constexpr char NamedLabel[] = "NamedLabel";
-
-struct TNameLabeled
- : public NActors::NMemory::TTrack<TNameLabeled, NamedLabel>
-{
- char payload[32];
-};
-
-#ifndef _win_
-Y_UNIT_TEST(Gathering)
-{
- TMemoryTracker::Instance()->Initialize();
-
- auto* typed = new TTypeLabeled;
- auto* typedArray = new TTypeLabeled[3];
-
- auto* named = new TNameLabeled;
- auto* namedArray = new TNameLabeled[5];
- NActors::NMemory::TLabel<NamedLabel>::Add(100);
-
- std::vector<TMetric> metrics;
- TMemoryTracker::Instance()->GatherMetrics(metrics);
-
- auto typeIndex = FindLabelIndex(TypeName<TTypeLabeled>().c_str());
- UNIT_ASSERT(typeIndex < metrics.size());
- UNIT_ASSERT(metrics[typeIndex].GetMemory() == sizeof(TTypeLabeled) * 4 + sizeof(size_t));
- UNIT_ASSERT(metrics[typeIndex].GetCount() == 2);
-
- auto nameIndex = FindLabelIndex(NamedLabel);
- UNIT_ASSERT(nameIndex < metrics.size());
- UNIT_ASSERT(metrics[nameIndex].GetMemory() == sizeof(TNameLabeled) * 6 + sizeof(size_t) + 100);
- UNIT_ASSERT(metrics[nameIndex].GetCount() == 3);
-
- NActors::NMemory::TLabel<NamedLabel>::Sub(100);
- delete [] namedArray;
- delete named;
-
- delete [] typedArray;
- delete typed;
-
- TMemoryTracker::Instance()->GatherMetrics(metrics);
-
- UNIT_ASSERT(metrics[typeIndex].GetMemory() == 0);
- UNIT_ASSERT(metrics[typeIndex].GetCount() == 0);
-
- UNIT_ASSERT(metrics[nameIndex].GetMemory() == 0);
- UNIT_ASSERT(metrics[nameIndex].GetCount() == 0);
-}
-#endif
-
-static constexpr char InContainerLabel[] = "InContainerLabel";
-
-struct TInContainer {
- char payload[16];
-};
-
-Y_UNIT_TEST(Containers) {
- TMemoryTracker::Instance()->Initialize();
-
- std::vector<TInContainer, NActors::NMemory::TAlloc<TInContainer>> vecT;
- vecT.resize(5);
-
- std::vector<TInContainer, NActors::NMemory::TAlloc<TInContainer, InContainerLabel>> vecN;
- vecN.resize(7);
-
- using TKey = int;
-
- std::map<TKey, TInContainer, std::less<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>>> mapT;
- mapT.emplace(0, TInContainer());
- mapT.emplace(1, TInContainer());
-
- std::map<TKey, TInContainer, std::less<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>, InContainerLabel>> mapN;
- mapN.emplace(0, TInContainer());
-
- std::unordered_map<TKey, TInContainer, std::hash<TKey>, std::equal_to<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>>> umapT;
- umapT.emplace(0, TInContainer());
-
- std::unordered_map<TKey, TInContainer, std::hash<TKey>, std::equal_to<TKey>,
- NActors::NMemory::TAlloc<std::pair<const TKey, TInContainer>, InContainerLabel>> umapN;
- umapN.emplace(0, TInContainer());
- umapN.emplace(1, TInContainer());
-
- std::vector<TMetric> metrics;
- TMemoryTracker::Instance()->GatherMetrics(metrics);
-
- auto indices = TMemoryTracker::Instance()->GetMetricIndices();
- for (auto& [name, index] : indices) {
- Cerr << "---- " << name
- << ": memory = " << metrics[index].GetMemory()
- << ", count = " << metrics[index].GetCount() << Endl;
- }
-
- auto vecTIndex = FindLabelIndex(TypeName<TInContainer>().c_str());
- UNIT_ASSERT(metrics[vecTIndex].GetMemory() >= ssize_t(sizeof(TInContainer) * 5));
- UNIT_ASSERT(metrics[vecTIndex].GetCount() == 1);
-
- auto labelIndex = FindLabelIndex(InContainerLabel);
- UNIT_ASSERT(metrics[labelIndex].GetCount() == 5);
- UNIT_ASSERT(metrics[labelIndex].GetMemory() >= ssize_t(
- sizeof(TInContainer) * 7 +
- sizeof(decltype(mapN)::value_type) +
- sizeof(decltype(umapN)::value_type) * 2));
-}
-
-
-static constexpr char InThreadLabel[] = "InThreadLabel";
-
-struct TInThread
- : public NActors::NMemory::TTrack<TInThread, InThreadLabel>
-{
- char payload[16];
-};
-
-void* ThreadProc(void*) {
- return new TInThread;
-}
-
-Y_UNIT_TEST(Threads) {
- TMemoryTracker::Instance()->Initialize();
-
- auto index = FindLabelIndex(InThreadLabel);
-
- auto* object1 = new TInThread;
-
- std::vector<TMetric> metrics;
- TMemoryTracker::Instance()->GatherMetrics(metrics);
- UNIT_ASSERT(metrics[index].GetMemory() == sizeof(TInThread));
- UNIT_ASSERT(metrics[index].GetCount() == 1);
-
- TThread thread(&ThreadProc, nullptr);
- thread.Start();
- auto* object2 = static_cast<TInThread*>(thread.Join());
-
- TMemoryTracker::Instance()->GatherMetrics(metrics);
- UNIT_ASSERT(metrics[index].GetMemory() == sizeof(TInThread) * 2);
- UNIT_ASSERT(metrics[index].GetCount() == 2);
-
- delete object2;
-
- TMemoryTracker::Instance()->GatherMetrics(metrics);
- UNIT_ASSERT(metrics[index].GetMemory() == sizeof(TInThread));
- UNIT_ASSERT(metrics[index].GetCount() == 1);
-
- delete object1;
-}
-
-
-struct TNotTracked {
- char payload[16];
-};
-
-struct TTracked
- : public NActors::NMemory::TTrack<TTracked>
-{
- char payload[16];
-};
-
-template <typename T>
-double MeasureAllocations() {
- constexpr size_t objectsCount = 4 << 20;
-
- std::vector<T*> objects;
- objects.resize(objectsCount);
-
- THPTimer timer;
-
- for (size_t i = 0; i < objectsCount; ++i) {
- objects[i] = new T;
- }
-
- for (size_t i = 0; i < objectsCount; ++i) {
- delete objects[i];
- }
-
- auto seconds = timer.Passed();
- Cerr << "---- objects: " << objectsCount << ", time: " << seconds << Endl;
- return seconds;
-}
-
-Y_UNIT_TEST(Performance) {
- TMemoryTracker::Instance()->Initialize();
-
- constexpr size_t Runs = 16;
-
- Cerr << "---- warmup" << Endl;
- MeasureAllocations<TNotTracked>();
- MeasureAllocations<TTracked>();
-
- std::vector<double> noTrack;
- std::vector<double> track;
-
- for (size_t run = 0; run < Runs; ++run) {
- Cerr << "---- no track" << Endl;
- auto time = MeasureAllocations<TNotTracked>();
- noTrack.push_back(time);
-
- Cerr << "---- track" << Endl;
- time = MeasureAllocations<TTracked>();
- track.push_back(time);
- }
-
- double meanNoTrack = 0, stddevNoTrack = 0;
- double meanTrack = 0, stddevTrack = 0;
- for (size_t i = 0; i < Runs; ++i) {
- meanNoTrack += noTrack[i];
- meanTrack += track[i];
- }
- meanNoTrack /= Runs;
- meanTrack /= Runs;
-
- auto sqr = [](double val) { return val * val; };
-
- for (size_t i = 0; i < Runs; ++i) {
- stddevNoTrack += sqr(noTrack[i] - meanNoTrack);
- stddevTrack += sqr(track[i] - meanTrack);
- }
- stddevNoTrack = sqrt(stddevNoTrack / (Runs - 1));
- stddevTrack = sqrt(stddevTrack / (Runs - 1));
-
- Cerr << "---- no track - mean: " << meanNoTrack << ", stddev: " << stddevNoTrack << Endl;
- Cerr << "---- track - mean: " << meanTrack << ", stddev: " << stddevTrack << Endl;
- Cerr << "---- tracking is slower by " << int((meanTrack / meanNoTrack - 1.0) * 100) << "%" << Endl;
-}
-
-#endif
-
-}
-
-}
-}
diff --git a/library/cpp/actors/util/named_tuple.h b/library/cpp/actors/util/named_tuple.h
deleted file mode 100644
index 67f185bba8..0000000000
--- a/library/cpp/actors/util/named_tuple.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include "defs.h"
-
-template <typename TDerived>
-struct TNamedTupleBase {
- friend bool operator==(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() == y.ConvertToTuple();
- }
-
- friend bool operator!=(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() != y.ConvertToTuple();
- }
-
- friend bool operator<(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() < y.ConvertToTuple();
- }
-
- friend bool operator<=(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() <= y.ConvertToTuple();
- }
-
- friend bool operator>(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() > y.ConvertToTuple();
- }
-
- friend bool operator>=(const TDerived& x, const TDerived& y) {
- return x.ConvertToTuple() >= y.ConvertToTuple();
- }
-};
diff --git a/library/cpp/actors/util/queue_chunk.h b/library/cpp/actors/util/queue_chunk.h
deleted file mode 100644
index 8a4e02d8cb..0000000000
--- a/library/cpp/actors/util/queue_chunk.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include "defs.h"
-
-template <typename T, ui32 TSize, typename TDerived>
-struct TQueueChunkDerived {
- static const ui32 EntriesCount = (TSize - sizeof(TQueueChunkDerived*)) / sizeof(T);
- static_assert(EntriesCount > 0, "expect EntriesCount > 0");
-
- volatile T Entries[EntriesCount];
- TDerived* volatile Next;
-
- TQueueChunkDerived() {
- memset(this, 0, sizeof(TQueueChunkDerived));
- }
-};
-
-template <typename T, ui32 TSize>
-struct TQueueChunk {
- static const ui32 EntriesCount = (TSize - sizeof(TQueueChunk*)) / sizeof(T);
- static_assert(EntriesCount > 0, "expect EntriesCount > 0");
-
- volatile T Entries[EntriesCount];
- TQueueChunk* volatile Next;
-
- TQueueChunk() {
- memset(this, 0, sizeof(TQueueChunk));
- }
-};
diff --git a/library/cpp/actors/util/queue_oneone_inplace.h b/library/cpp/actors/util/queue_oneone_inplace.h
deleted file mode 100644
index 288011955a..0000000000
--- a/library/cpp/actors/util/queue_oneone_inplace.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#pragma once
-
-#include "defs.h"
-#include "queue_chunk.h"
-
-template <typename T, ui32 TSize, typename TChunk = TQueueChunk<T, TSize>>
-class TOneOneQueueInplace : TNonCopyable {
- static_assert(std::is_integral<T>::value || std::is_pointer<T>::value, "expect std::is_integral<T>::value || std::is_pointer<T>::valuer");
-
- TChunk* ReadFrom;
- ui32 ReadPosition;
- ui32 WritePosition;
- TChunk* WriteTo;
-
- friend class TReadIterator;
-
-public:
- class TReadIterator {
- TChunk* ReadFrom;
- ui32 ReadPosition;
-
- public:
- TReadIterator(TChunk* readFrom, ui32 readPosition)
- : ReadFrom(readFrom)
- , ReadPosition(readPosition)
- {
- }
-
- inline T Next() {
- TChunk* head = ReadFrom;
- if (ReadPosition != TChunk::EntriesCount) {
- return AtomicLoad(&head->Entries[ReadPosition++]);
- } else if (TChunk* next = AtomicLoad(&head->Next)) {
- ReadFrom = next;
- ReadPosition = 0;
- return Next();
- }
- return T{};
- }
- };
-
- TOneOneQueueInplace()
- : ReadFrom(new TChunk())
- , ReadPosition(0)
- , WritePosition(0)
- , WriteTo(ReadFrom)
- {
- }
-
- ~TOneOneQueueInplace() {
- Y_DEBUG_ABORT_UNLESS(Head() == 0);
- delete ReadFrom;
- }
-
- struct TPtrCleanDestructor {
- static inline void Destroy(TOneOneQueueInplace<T, TSize>* x) noexcept {
- while (T head = x->Pop())
- delete head;
- delete x;
- }
- };
-
- struct TCleanDestructor {
- static inline void Destroy(TOneOneQueueInplace<T, TSize>* x) noexcept {
- while (x->Pop() != nullptr)
- continue;
- delete x;
- }
- };
-
- struct TPtrCleanInplaceMallocDestructor {
- template <typename TPtrVal>
- static inline void Destroy(TOneOneQueueInplace<TPtrVal*, TSize>* x) noexcept {
- while (TPtrVal* head = x->Pop()) {
- head->~TPtrVal();
- free(head);
- }
- delete x;
- }
- };
-
- void Push(T x) noexcept {
- if (WritePosition != TChunk::EntriesCount) {
- AtomicStore(&WriteTo->Entries[WritePosition], x);
- ++WritePosition;
- } else {
- TChunk* next = new TChunk();
- next->Entries[0] = x;
- AtomicStore(&WriteTo->Next, next);
- WriteTo = next;
- WritePosition = 1;
- }
- }
-
- T Head() {
- TChunk* head = ReadFrom;
- if (ReadPosition != TChunk::EntriesCount) {
- return AtomicLoad(&head->Entries[ReadPosition]);
- } else if (TChunk* next = AtomicLoad(&head->Next)) {
- ReadFrom = next;
- delete head;
- ReadPosition = 0;
- return Head();
- }
- return T{};
- }
-
- T Pop() {
- T ret = Head();
- if (ret)
- ++ReadPosition;
- return ret;
- }
-
- TReadIterator Iterator() {
- return TReadIterator(ReadFrom, ReadPosition);
- }
-};
diff --git a/library/cpp/actors/util/rc_buf.cpp b/library/cpp/actors/util/rc_buf.cpp
deleted file mode 100644
index 946c9846ee..0000000000
--- a/library/cpp/actors/util/rc_buf.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "rc_buf.h"
-
-template<>
-void Out<TRcBuf>(IOutputStream& s, const TRcBuf& x) {
- s.Write(TStringBuf(x));
-}
diff --git a/library/cpp/actors/util/rc_buf.h b/library/cpp/actors/util/rc_buf.h
deleted file mode 100644
index db0f7deff5..0000000000
--- a/library/cpp/actors/util/rc_buf.h
+++ /dev/null
@@ -1,1120 +0,0 @@
-#pragma once
-
-#include <atomic>
-#include <new>
-
-#include <util/generic/ptr.h>
-#include <util/generic/string.h>
-#include <util/generic/hash_set.h>
-#include <util/generic/scope.h>
-#include <util/stream/str.h>
-#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"
-#include "rc_buf_backend.h"
-
-#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW
-#include "shared_data_backtracing_owner.h"
-#endif
-
-namespace NContiguousDataDetails {
- template<typename TContainer>
- struct TContainerTraits {
- static char* UnsafeGetDataMut(const TContainer& backend) {
- return const_cast<char*>(backend.data());
- }
- };
-} // NContiguousDataDetails
-
-class TContiguousSpan
-{
-private:
- const char *Data_ = nullptr;
- size_t Size_ = 0;
-
-public:
- TContiguousSpan() = default;
-
- TContiguousSpan(const char *data, size_t size)
- : Data_(data)
- , Size_(size)
- {}
-
- TContiguousSpan(const TString& str)
- : Data_(str.data())
- , Size_(str.size())
- {}
-
- TContiguousSpan(const TStringBuf& str)
- : Data_(str.data())
- , Size_(str.size())
- {}
-
- TContiguousSpan(const TArrayRef<char>& ref)
- : Data_(ref.data())
- , Size_(ref.size())
- {}
-
- TContiguousSpan(const TArrayRef<const char>& ref)
- : Data_(ref.data())
- , Size_(ref.size())
- {}
-
- TContiguousSpan(const NActors::TSharedData& data)
- : Data_(data.data())
- , Size_(data.size())
- {}
-
- const char& operator[](size_t index) const {
- Y_DEBUG_ABORT_UNLESS(index < Size_);
- return Data_[index];
- }
-
- const char *data() const noexcept {
- return Data_;
- }
-
- size_t size() const noexcept {
- return Size_;
- }
-
- const char *GetData() const noexcept {
- return Data_;
- }
-
- size_t GetSize() const noexcept {
- return Size_;
- }
-
- const char *Data() const noexcept {
- return Data_;
- }
-
- size_t Size() const noexcept {
- return Size_;
- }
-
- TContiguousSpan SubSpan(size_t pos, size_t n) const noexcept {
- pos = Min(pos, size());
- n = Min(n, size() - pos);
- return TContiguousSpan(data() + pos, n);
- }
-
- template<std::size_t Index>
- auto get() const noexcept
- {
- static_assert(Index < 2,
- "Index out of bounds for TContiguousSpan");
- if constexpr (Index == 0) return Data_;
- if constexpr (Index == 1) return Size_;
- }
-
- friend bool operator==(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) >= 0; }
-
-private:
- static int Compare(const TContiguousSpan& x, const TContiguousSpan& y) {
- int res = 0;
- if (const size_t common = std::min(x.size(), y.size())) {
- res = std::memcmp(x.data(), y.data(), common);
- }
- return res ? res : x.size() - y.size();
- }
-};
-
-
-
-namespace std
-{
- template<>
- struct tuple_size<::TContiguousSpan>
- : integral_constant<size_t, 2> {};
-
- template<>
- struct tuple_element<0, ::TContiguousSpan>
- {
- using type = const char *;
- };
-
- template<>
- struct tuple_element<1, ::TContiguousSpan>
- {
- using type = size_t;
- };
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator==(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) == TContiguousSpan(rhs);
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator!=(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) != TContiguousSpan(rhs);
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator<(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) < TContiguousSpan(rhs);
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator<=(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) <= TContiguousSpan(rhs);
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator>(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) > TContiguousSpan(rhs);
-}
-
-template <
- class TLeft,
- class TRight,
- typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
- typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
- >
-bool operator>=(const TLeft& lhs, const TRight& rhs) {
- return TContiguousSpan(lhs) >= TContiguousSpan(rhs);
-}
-
-
-class TMutableContiguousSpan
-{
-private:
- char *Data = nullptr;
- size_t Size = 0;
-
-public:
- TMutableContiguousSpan() = default;
-
- TMutableContiguousSpan(char *data, size_t size)
- : Data(data)
- , Size(size)
- {}
-
- char *data() noexcept {
- return Data;
- }
-
- char *GetData() noexcept {
- return Data;
- }
-
- TMutableContiguousSpan SubSpan(size_t pos, size_t n) noexcept {
- pos = Min(pos, size());
- n = Min(n, size() - pos);
- return TMutableContiguousSpan(data() + pos, n);
- }
-
- const char *data() const noexcept {
- return Data;
- }
-
- size_t size() const noexcept {
- return Size;
- }
-
- const char *GetData() const noexcept {
- return Data;
- }
-
- size_t GetSize() const noexcept {
- return Size;
- }
-
- TContiguousSpan SubSpan(size_t pos, size_t n) const noexcept {
- pos = Min(pos, size());
- n = Min(n, size() - pos);
- return TContiguousSpan(data() + pos, n);
- }
-
- operator TContiguousSpan() const noexcept {
- return TContiguousSpan(Data, Size);
- }
-};
-
-struct IContiguousChunk : TThrRefBase {
- using TPtr = TIntrusivePtr<IContiguousChunk>;
-
- virtual ~IContiguousChunk() = default;
-
- /**
- * Should give immutable access to data
- */
- virtual TContiguousSpan GetData() const = 0;
-
- /**
- * Should give mutable access to underlying data
- * If data is shared - data should be copied
- * E.g. for TString str.Detach() should be used
- * Possibly invalidates previous *GetData*() calls
- */
- virtual TMutableContiguousSpan GetDataMut() = 0;
-
- /**
- * Should give mutable access to undelying data as fast as possible
- * Even if data is shared this property should be ignored
- * E.g. in TString const_cast<char *>(str.data()) should be used
- * Possibly invalidates previous *GetData*() calls
- */
- virtual TMutableContiguousSpan UnsafeGetDataMut() {
- 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;
-};
-
-class TRope;
-class TRopeArena;
-
-class TRcBuf {
- friend class TRope;
- friend class TRopeArena;
-
- using TInternalBackend = NDetail::TRcBufInternalBackend;
-
- class TBackend {
- enum class EType : uintptr_t {
- STRING,
- SHARED_DATA,
- INTERNAL_BACKEND,
- EXTERNAL_BACKEND,
- };
-
- struct TBackendHolder {
- uintptr_t Data[2];
- explicit operator bool() const noexcept {
- return Data[0] || Data[1];
- }
- friend bool operator ==(const TBackendHolder& x, const TBackendHolder& y) {
- return x.Data[0] == y.Data[0] && x.Data[1] == y.Data[1];
- }
- };
-
- constexpr static TBackendHolder Empty = {0, 0};
-
-#ifndef TSTRING_IS_STD_STRING
- 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:
- using TCookies = TInternalBackend::TCookies;
-
- static constexpr struct TControlToken {} ControlToken;
- static constexpr size_t CookiesSize = sizeof(TCookies);
-
- TBackend() = default;
-
- TBackend(const TBackend& other)
- : Owner(other.Owner ? Clone(other.Owner) : TBackend::Empty)
- {}
-
- TBackend(TBackend&& other)
- : Owner(std::exchange(other.Owner, TBackend::Empty))
- {}
-
- TBackend(TString s)
- : Owner(Construct<TString>(EType::STRING, std::move(s)))
- {}
-
- TBackend(NActors::TSharedData 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::EXTERNAL_BACKEND, std::move(backend)))
- {}
-
- ~TBackend() {
- if (Owner) {
- Destroy(Owner);
- }
- }
-
- TBackend& operator =(const TBackend& other) {
- if (Y_UNLIKELY(this == &other)) {
- return *this;
- }
-
- if (Owner) {
- Destroy(Owner);
- }
- if (other.Owner) {
- Owner = Clone(other.Owner);
- } else {
- Owner = TBackend::Empty;
- }
- return *this;
- }
-
- TBackend& operator =(TBackend&& other) {
- if (Y_UNLIKELY(this == &other)) {
- return *this;
- }
-
- if (Owner) {
- Destroy(Owner);
- }
- Owner = std::exchange(other.Owner, TBackend::Empty);
- return *this;
- }
-
- bool operator ==(const TBackend& other) const {
- return Owner == other.Owner;
- }
-
- const void *UniqueId() const {
- return reinterpret_cast<const void*>(Owner.Data[0]);
- }
-
- TCookies* GetCookies() {
- if(!Owner) {
- return nullptr;
- }
- return Visit(Owner, [](EType, auto& value) -> TCookies* {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TInternalBackend>) {
- return value.GetCookies();
- } 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> || 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 {
- static_assert(TDependentFalse<T>);
- }
- });
- }
-
- TContiguousSpan GetData() const {
- if (!Owner) {
- return TContiguousSpan();
- }
- return Visit(Owner, [](EType, auto& value) -> TContiguousSpan {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TString> || 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();
- } else {
- static_assert(TDependentFalse<T>, "unexpected type");
- }
- });
- }
-
- TMutableContiguousSpan GetDataMut() {
- if (!Owner) {
- return 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()};
- } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
- if (value.IsShared()) {
- 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 {
- static_assert(TDependentFalse<T>, "unexpected type");
- }
- });
- }
-
- TMutableContiguousSpan UnsafeGetDataMut() const {
- if (!Owner) {
- return 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> || 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();
- } else {
- static_assert(TDependentFalse<T>, "unexpected type");
- }
- });
- }
-
- size_t GetOccupiedMemorySize() const {
- if (!Owner) {
- return 0;
- }
- return Visit(Owner, [](EType, auto& value) {
- 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> || 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();
- } else {
- static_assert(TDependentFalse<T>, "unexpected type");
- }
- });
- }
-
- template <class TType>
- bool ContainsNativeType() const {
- if (!Owner) {
- return false;
- }
- return Visit(Owner, [](EType, auto& value) {
- using T = std::decay_t<decltype(value)>;
- return std::is_same_v<T, TType>;
- });
- }
-
- bool CanGrowFront(const char* begin) const {
- if (!Owner) {
- return false;
- }
- const TCookies* cookies = GetCookies();
- return cookies && (IsPrivate() || cookies->Begin.load() == begin);
- }
-
- bool CanGrowBack(const char* end) const {
- if (!Owner) {
- return false;
- }
- const TCookies* cookies = GetCookies();
- return cookies && (IsPrivate() || cookies->End.load() == end);
- }
-
- void UpdateCookiesUnsafe(const char* contBegin, const char* contEnd) {
- if (!Owner) {
- return;
- }
- TCookies* cookies = GetCookies();
- if (cookies) {
- cookies->Begin.store(contBegin);
- cookies->End.store(contEnd);
- }
- }
-
- bool UpdateCookiesBegin(const char* curBegin, const char* contBegin) {
- if (!Owner) {
- 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;
- }
-
- TCookies* cookies = GetCookies();
- if (cookies) {
- return cookies->End.compare_exchange_weak(curEnd, contEnd);
- }
- return false;
- }
-
- template <typename TResult, typename TCallback>
- std::invoke_result_t<TCallback, const TResult*> ApplySpecificValue(TCallback&& callback) const {
- static_assert(std::is_same_v<TResult, TString> ||
- std::is_same_v<TResult, NActors::TSharedData> ||
- std::is_same_v<TResult, TInternalBackend> ||
- std::is_same_v<TResult, IContiguousChunk::TPtr>);
-
- if (!Owner) {
- return callback(nullptr);
- }
- return Visit(Owner, [&](EType, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TResult>) {
- return callback(&value);
- } else {
- return callback(nullptr);
- }
- });
- }
-
- explicit operator bool() const {
- return static_cast<bool>(Owner);
- }
-
- private:
- static constexpr uintptr_t TypeMask = (1 << 3) - 1;
- static constexpr uintptr_t ValueMask = ~TypeMask;
-
- template<typename T>
- struct TObjectHolder {
- struct TWrappedObject : TThrRefBase {
- T Value;
- TWrappedObject(T&& value)
- : Value(std::move(value))
- {}
- };
- TIntrusivePtr<TWrappedObject> Object;
-
- TObjectHolder(T&& object)
- : Object(MakeIntrusive<TWrappedObject>(std::move(object)))
- {}
- };
-
- template<typename TObject>
- static TBackendHolder Construct(EType type, TObject&& object) {
- if constexpr (sizeof(TObject) <= sizeof(TBackendHolder)) {
- TBackendHolder res = TBackend::Empty;
- new(&res) std::decay_t<TObject>(std::forward<TObject>(object));
- Y_DEBUG_ABORT_UNLESS((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::forward<TObject>(object)));
- }
- }
-
- template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
- static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> VisitRaw(TOwner& origValue, TCallback&& callback) {
- Y_DEBUG_ABORT_UNLESS(origValue);
- const EType type = static_cast<EType>(origValue.Data[0] & TypeMask);
- TBackendHolder value(origValue);
- value.Data[0] = value.Data[0] & ValueMask;
- // bring object type back
- Y_SCOPE_EXIT(&value, &origValue, type){
- if constexpr(!IsConst) {
- value.Data[0] = value.Data[0] | static_cast<uintptr_t>(type);
- origValue = value;
- } else {
- Y_UNUSED(value);
- Y_UNUSED(origValue);
- Y_UNUSED(type);
- }
- };
- auto caller = [&](auto& value) { return std::invoke(std::forward<TCallback>(callback), type, value); };
- auto wrapper = [&](auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (sizeof(T) <= sizeof(TBackendHolder)) {
- return caller(value);
- } else {
- return caller(reinterpret_cast<std::conditional_t<IsConst, const TObjectHolder<T>&, TObjectHolder<T>&>>(value));
- }
- };
- switch (type) {
- case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value));
- case EType::SHARED_DATA: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const NActors::TSharedData&, NActors::TSharedData&>>(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_ABORT("Unexpected type# %" PRIu64, static_cast<ui64>(type));
- }
-
- template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
- static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> Visit(TOwner& value, TCallback&& callback) {
- return VisitRaw(value, [&](EType type, auto& value) {
- return std::invoke(std::forward<TCallback>(callback), type, Unwrap(value));
- });
- }
-
- template<typename T> static T& Unwrap(T& object) { return object; }
- template<typename T> static T& Unwrap(TObjectHolder<T>& holder) { return holder.Object->Value; }
- template<typename T> static const T& Unwrap(const TObjectHolder<T>& holder) { return holder.Object->Value; }
-
- template<typename TOwner>
- static TBackendHolder Clone(TOwner& value) {
- return VisitRaw(value, [](EType type, auto& value) { return Construct(type, value); });
- }
-
- template<typename TOwner>
- static void Destroy(TOwner& value) {
- VisitRaw(value, [](EType, auto& value) { CallDtor(value); });
- }
-
- template<typename T>
- static void CallDtor(T& value) {
- value.~T();
- }
- };
-
- static constexpr struct TOwnedPiece {} OwnedPiece{};
-
- TBackend Backend; // who actually holds the data
- const char *Begin; // data start
- const char *End; // data end
-
- explicit TRcBuf(TInternalBackend s, const char *data, size_t size)
- : Backend(std::move(s))
- {
- Y_ABORT_UNLESS(Backend.GetData().data() == nullptr ||
- (Backend.GetCookies() && Backend.GetCookies()->Begin == data && Backend.GetCookies()->End == data + size));
- Begin = data;
- End = data + size;
- }
-
- explicit TRcBuf(TInternalBackend s)
- : Backend(std::move(s))
- {
- auto span = Backend.GetData();
- Begin = span.data();
- End = Begin + span.size();
- }
-
- TRcBuf(TOwnedPiece, const char *data, size_t size, const TRcBuf& from)
- : TRcBuf(from.Backend, {data, size})
- {
- Y_ABORT_UNLESS(data >= from.GetData());
- Y_ABORT_UNLESS(data < from.GetData() + from.GetSize());
- Y_ABORT_UNLESS(data + size <= from.GetData() + from.GetSize());
- Backend.UpdateCookiesUnsafe(Begin, End);
- }
-
- TRcBuf(TOwnedPiece, const char *begin, const char *end, const TRcBuf& from)
- : TRcBuf(OwnedPiece, begin, end - begin, from)
- {}
-
-public:
- static constexpr struct TPiece {} Piece{};
-
- enum class EResizeResult {
- NoAlloc,
- Alloc,
- };
-
- enum class EResizeStrategy {
- KeepRooms,
- FailOnCopy,
- // SaveAllocs, // Move data if there is enough space in (headroom + size + tailroom)
- };
-
- TRcBuf()
- : Begin(nullptr)
- , End(nullptr)
- {}
-
- template<typename T>
- TRcBuf(T&& backend, const TContiguousSpan& data)
- : Backend(std::forward<T>(backend))
- , Begin(data.data())
- , End(Begin + data.size())
- {}
-
- explicit TRcBuf(TString s)
- : Backend(std::move(s))
- {
- auto span = Backend.GetData();
- Begin = span.data();
- End = Begin + span.size();
- }
-
- explicit TRcBuf(NActors::TSharedData s)
- : Backend(std::move(s))
- {
- auto span = Backend.GetData();
- Begin = span.data();
- End = Begin + span.size();
- }
-
- TRcBuf(IContiguousChunk::TPtr backend)
- : TRcBuf(backend, backend->GetData())
- {}
-
- TRcBuf(TPiece, const char *data, size_t size, const TRcBuf& from)
- : TRcBuf(from.Backend, {data, size})
- {
- Y_ABORT_UNLESS(data >= from.GetData());
- Y_ABORT_UNLESS(data < from.GetData() + from.GetSize());
- Y_ABORT_UNLESS(data + size <= from.GetData() + from.GetSize());
- }
-
- TRcBuf(TPiece, const char *begin, const char *end, const TRcBuf& from)
- : TRcBuf(Piece, begin, end - begin, from)
- {}
-
- TRcBuf(const TRcBuf& other)
- : Backend(other.Backend)
- , Begin(other.Begin)
- , End(other.End)
- {}
-
- TRcBuf(TRcBuf&& other)
- : Backend(std::move(other.Backend))
- , Begin(other.Begin)
- , End(other.End)
- {}
-
- TRcBuf& operator =(const TRcBuf&) = default;
- TRcBuf& operator =(TRcBuf&&) = default;
-
- static TRcBuf Uninitialized(size_t size, size_t headroom = 0, size_t tailroom = 0)
- {
- if (size == 0) {
- return TRcBuf();
- }
-
- if (headroom == 0 && tailroom == 0) {
- TInternalBackend res = TInternalBackend::Uninitialized(size);
- return TRcBuf(
- OwnedPiece,
- res.data(),
- res.data() + res.size(),
- TRcBuf(res));
- }
-
- TInternalBackend res = TInternalBackend::Uninitialized(size, headroom, tailroom);
- return TRcBuf(res, res.data() + headroom, size);
- }
-
- static TRcBuf Copy(TContiguousSpan data, size_t headroom = 0, size_t tailroom = 0) {
- TRcBuf res = Uninitialized(data.size(), headroom, tailroom);
- std::memcpy(res.UnsafeGetDataMut(), data.GetData(), data.GetSize());
- return res;
- }
-
- static TRcBuf Copy(const char* data, size_t size, size_t headroom = 0, size_t tailroom = 0) {
- return Copy({data, size}, headroom, tailroom);
- }
-
- template <class TType>
- bool ContainsNativeType() const {
- return Backend.ContainsNativeType<TType>();
- }
-
- bool CanGrowFront() const noexcept {
- return Backend.CanGrowFront(Begin);
- }
-
- bool CanGrowBack() const noexcept {
- return Backend.CanGrowBack(End);
- }
-
- size_t GetSize() const {
- return End - Begin;
- }
-
- size_t Size() const {
- return End - Begin;
- }
-
- size_t GetOccupiedMemorySize() const {
- return Backend.GetOccupiedMemorySize();
- }
-
- const char* GetData() const {
- return Begin;
- }
-
- 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() {
- const char* oldBegin = Backend.GetData().data();
- ptrdiff_t offset = Begin - oldBegin;
- size_t size = GetSize();
- char* newBegin = Backend.UnsafeGetDataMut().data();
- Begin = newBegin + offset;
- End = Begin + size;
- return newBegin + offset;
- }
-
- template <class TResult>
- TResult ExtractUnderlyingContainerOrCopy() const {
- static_assert(std::is_same_v<TResult, TString> ||
- std::is_same_v<TResult, NActors::TSharedData> ||
- std::is_same_v<TResult, TInternalBackend>);
-
- constexpr bool isSharedData = std::is_same_v<TResult, NActors::TSharedData>;
- TResult res;
-
- const bool found = Backend.ApplySpecificValue<TResult>([&](const TResult *raw) {
- if (raw && raw->data() == Begin && (isSharedData ? End <= Begin + raw->size() : End == Begin + raw->size())) {
- if constexpr (isSharedData) {
- raw->TrimBack(size());
- }
- res = TResult(*raw);
- return true;
- }
- return false;
- });
-
- if (!found) {
- res = TResult::Uninitialized(GetSize());
- char* data = NContiguousDataDetails::TContainerTraits<TResult>::UnsafeGetDataMut(res);
- std::memcpy(data, GetData(), GetSize());
- }
-
- return res;
- }
-
- TContiguousSpan GetContiguousSpan() const {
- return {GetData(), GetSize()};
- }
-
- TStringBuf Slice(size_t pos = 0, size_t len = Max<size_t>()) const noexcept {
- pos = Min(pos, size());
- len = Min(len, size() - pos);
- return {const_cast<TRcBuf*>(this)->UnsafeGetDataMut() + pos, len};
- }
-
- explicit operator TStringBuf() const noexcept {
- return Slice();
- }
-
- TMutableContiguousSpan GetContiguousSpanMut() {
- return {GetDataMut(), GetSize()};
- }
-
- TMutableContiguousSpan UnsafeGetContiguousSpanMut() {
- return {UnsafeGetDataMut(), GetSize()};
- }
-
- bool HasBuffer() const {
- return static_cast<bool>(Backend);
- }
-
- size_t size() const {
- return GetSize();
- }
-
- bool empty() const {
- return !static_cast<bool>(Backend);
- }
-
- operator bool() const {
- return !empty();
- }
-
- const char* data() const {
- return GetData();
- }
-
- const char* Data() const {
- return GetData();
- }
-
- const char* begin() const {
- return Begin;
- }
-
- const char* end() const {
- return End;
- }
-
- char& operator[](size_t pos) {
- return UnsafeGetDataMut()[pos];
- }
-
- const char& operator[](size_t pos) const {
- return GetData()[pos];
- }
-
- void reserve(size_t size) {
- ReserveTailroom(size);
- }
-
- void ReserveHeadroom(size_t size) {
- if (Headroom() >= size) {
- return;
- }
- auto newData = TRcBuf::Uninitialized(GetSize(), size, UnsafeTailroom());
- if (auto data = GetData(); data) {
- std::memcpy(newData.UnsafeGetDataMut(), GetData(), GetSize());
- }
- *this = std::move(newData);
- }
-
- void ReserveTailroom(size_t size) {
- if (Tailroom() >= size) {
- return;
- }
- auto newData = TRcBuf::Uninitialized(GetSize(), UnsafeHeadroom(), size);
- if (auto data = GetData(); data) {
- std::memcpy(newData.UnsafeGetDataMut(), GetData(), GetSize());
- }
- *this = std::move(newData);
- }
-
- void ReserveBidi(size_t headroom, size_t tailroom) {
- if (Headroom() >= headroom && Tailroom() >= tailroom) {
- return;
- }
- auto newData = TRcBuf::Uninitialized(
- GetSize(),
- std::max(UnsafeHeadroom(), headroom),
- std::max(UnsafeTailroom(), tailroom));
- if (auto data = GetData(); data) {
- std::memcpy(newData.UnsafeGetDataMut(), GetData(), GetSize());
- }
- *this = std::move(newData);
- }
-
- EResizeResult GrowFront(size_t size, EResizeStrategy strategy = EResizeStrategy::KeepRooms) {
- if (Headroom() >= size && Backend.UpdateCookiesBegin(Begin, Begin - size)) {
- Begin -= size;
- return EResizeResult::NoAlloc;
- } else {
- if (strategy == EResizeStrategy::FailOnCopy && static_cast<bool>(Backend)) {
- Y_ABORT("Fail on grow");
- }
- auto newData = TRcBuf::Uninitialized(size + GetSize(), UnsafeHeadroom() > size ? UnsafeHeadroom() - size : 0, UnsafeTailroom());
- if (auto data = GetData(); data) {
- std::memcpy(newData.UnsafeGetDataMut() + size, GetData(), GetSize());
- }
- *this = std::move(newData);
- return EResizeResult::Alloc;
- }
- }
-
- EResizeResult GrowBack(size_t size, EResizeStrategy strategy = EResizeStrategy::KeepRooms) {
- if (Tailroom() > size && Backend.UpdateCookiesEnd(End, End + size)) {
- End += size;
- return EResizeResult::NoAlloc;
- } else {
- if (strategy == EResizeStrategy::FailOnCopy && static_cast<bool>(Backend)) {
- Y_ABORT("Fail on grow");
- }
- auto newData = TRcBuf::Uninitialized(size + GetSize(), UnsafeHeadroom(), UnsafeTailroom() > size ? UnsafeTailroom() - size : 0);
- if (auto data = GetData(); data) {
- std::memcpy(newData.UnsafeGetDataMut(), GetData(), GetSize());
- }
- *this = std::move(newData);
- return EResizeResult::Alloc;
- }
- }
-
- void TrimBack(size_t size) {
- Y_ABORT_UNLESS(size <= GetSize());
- End = End - (GetSize() - size);
- }
-
- void TrimFront(size_t size) {
- Y_ABORT_UNLESS(size <= GetSize());
- Begin = Begin + (GetSize() - size);
- }
-
- char* Detach() {
- return GetDataMut();
- }
-
- bool IsPrivate() const {
- return Backend.IsPrivate();
- }
-
- size_t UnsafeHeadroom() const {
- return Begin - Backend.GetData().data();
- }
-
- size_t UnsafeTailroom() const {
- auto span = Backend.GetData();
- return (span.GetData() + span.GetSize()) - End;
- }
-
- size_t Headroom() const {
- if (Backend.CanGrowFront(Begin)) {
- return UnsafeHeadroom();
- }
-
- return 0;
- }
-
- size_t Tailroom() const {
- if (Backend.CanGrowBack(End)) {
- return UnsafeTailroom();
- }
-
- return 0;
- }
-
- operator TContiguousSpan() const noexcept {
- return TContiguousSpan(GetData(), GetSize());
- }
-
- explicit operator TMutableContiguousSpan() noexcept {
- return TMutableContiguousSpan(GetDataMut(), GetSize());
- }
-};
diff --git a/library/cpp/actors/util/rc_buf_backend.h b/library/cpp/actors/util/rc_buf_backend.h
deleted file mode 100644
index 9cb8616554..0000000000
--- a/library/cpp/actors/util/rc_buf_backend.h
+++ /dev/null
@@ -1,230 +0,0 @@
-#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 TRcBufInternalBackend {
-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:
- TRcBufInternalBackend() noexcept
- : Data_(nullptr)
- , Size_(0)
- { }
-
- ~TRcBufInternalBackend() noexcept {
- Release();
- }
-
- TRcBufInternalBackend(const TRcBufInternalBackend& other) noexcept
- : Data_(other.Data_)
- , Size_(other.Size_)
- {
- AddRef();
- }
-
- TRcBufInternalBackend(TRcBufInternalBackend&& other) noexcept
- : Data_(other.Data_)
- , Size_(other.Size_)
- {
- other.Data_ = nullptr;
- other.Size_ = 0;
- }
-
- TRcBufInternalBackend& operator=(const TRcBufInternalBackend& other) noexcept {
- if (this != &other) {
- Release();
- Data_ = other.Data_;
- Size_ = other.Size_;
- AddRef();
- }
- return *this;
- }
-
- TRcBufInternalBackend& operator=(TRcBufInternalBackend&& 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 = TRcBufInternalBackend::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 TRcBufInternalBackend AttachUnsafe(char* data, size_t size) noexcept {
- TRcBufInternalBackend result;
- result.Data_ = data;
- result.Size_ = size;
- return result;
- }
-
- /**
- * Make uninitialized buffer of the specified size
- */
- static TRcBufInternalBackend 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 TRcBufInternalBackend Copy(const void* data, size_t size) {
- TRcBufInternalBackend result = Uninitialized(size);
- if (size) {
- ::memcpy(result.Data(), data, size);
- }
- return result;
- }
-
-private:
- Y_FORCE_INLINE THeader* Header() const noexcept {
- Y_DEBUG_ABORT_UNLESS(Data_);
- return reinterpret_cast<THeader*>(Data_);
- }
-
- Y_FORCE_INLINE char* Data() const noexcept {
- Y_DEBUG_ABORT_UNLESS(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/rc_buf_ut.cpp b/library/cpp/actors/util/rc_buf_ut.cpp
deleted file mode 100644
index c23e8b68d0..0000000000
--- a/library/cpp/actors/util/rc_buf_ut.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include "rc_buf.h"
-#include "ut_helpers.h"
-#include "rope.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-
-Y_UNIT_TEST_SUITE(TRcBuf) {
- Y_UNIT_TEST(TypeSize) {
- UNIT_ASSERT_EQUAL(sizeof(TRcBuf), 4 * sizeof(uintptr_t));
- }
-
- Y_UNIT_TEST(Slice) {
- auto data = TRcBuf::Copy("Hello", 5);
- UNIT_ASSERT_VALUES_EQUAL(TString(TStringBuf(data)), TString("Hello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice()), TString("Hello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1)), TString("ello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 3)), TString("ell"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 100)), TString("ello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(0, 4)), TString("Hell"));
- }
-
- Y_UNIT_TEST(CrossCompare) {
- TString str = "some very long string";
- const TString constStr(str);
- TStringBuf strbuf = str;
- const TStringBuf constStrbuf = str;
- TContiguousSpan span(str);
- const TContiguousSpan constSpan(str);
- TMutableContiguousSpan mutableSpan(const_cast<char*>(str.data()), str.size());
- const TMutableContiguousSpan constMutableSpan(const_cast<char*>(str.data()), str.size());
- TRcBuf data(str);
- const TRcBuf constData(str);
- TArrayRef<char> arrRef(const_cast<char*>(str.data()), str.size());
- const TArrayRef<char> constArrRef(const_cast<char*>(str.data()), str.size());
- TArrayRef<const char> arrConstRef(const_cast<char*>(str.data()), str.size());
- const TArrayRef<const char> constArrConstRef(const_cast<char*>(str.data()), str.size());
- NActors::TSharedData sharedData = NActors::TSharedData::Copy(str.data(), str.size());
- const NActors::TSharedData constSharedData(sharedData);
-
- Permutate(
- [](auto& arg1, auto& arg2) {
- UNIT_ASSERT(arg1 == arg2);
- },
- str,
- constStr,
- strbuf,
- constStrbuf,
- span,
- constSpan,
- mutableSpan,
- constMutableSpan,
- data,
- constData,
- arrRef,
- constArrRef,
- arrConstRef,
- constArrConstRef,
- sharedData,
- constSharedData);
- }
-
- Y_UNIT_TEST(Detach) {
- TRcBuf data = TRcBuf::Copy(TString("test"));
- TRcBuf data2 = data;
- char* res = data2.Detach();
- UNIT_ASSERT_UNEQUAL(data.GetData(), data2.GetData());
- UNIT_ASSERT_EQUAL(res, data2.GetData());
- UNIT_ASSERT_EQUAL(::memcmp(res, "test", 4), 0);
- UNIT_ASSERT_EQUAL(::memcmp(data.GetData(), "test", 4), 0);
- }
-
- Y_UNIT_TEST(Resize) {
- TRcBuf data = TRcBuf::Uninitialized(10, 20, 30);
- UNIT_ASSERT_EQUAL(data.size(), 10);
- UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- 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(), 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(), 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(), 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);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 0);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 73);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom());
- }
-
- Y_UNIT_TEST(ResizeUnshare) {
- TRcBuf data = TRcBuf::Uninitialized(10, 20, 30);
- TRcBuf otherData(data);
- UNIT_ASSERT_EQUAL(data.data(), otherData.data());
- UNIT_ASSERT_EQUAL(data.size(), 10);
- UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- 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(), 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(), 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(), 30);
- UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 60);
- data.TrimBack(15);
- data.TrimFront(10);
- UNIT_ASSERT_EQUAL(data.size(), 10);
- UNIT_ASSERT_EQUAL(data.Headroom(), 20);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 30);
- UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60);
- }
-
- Y_UNIT_TEST(Trim) {
- TRcBuf data = TRcBuf::Uninitialized(10, 20, 30);
- TRcBuf otherData(data);
- otherData.TrimBack(5);
- UNIT_ASSERT_EQUAL(data.data(), otherData.data());
- UNIT_ASSERT_EQUAL(otherData.Headroom(), 20);
- UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0);
- TRcBuf otherData2(data);
- otherData2.TrimBack(2);
- otherData2.TrimFront(1);
- UNIT_ASSERT_EQUAL(data.data() + 1, otherData2.data());
- UNIT_ASSERT_EQUAL(otherData2.Headroom(), 0);
- UNIT_ASSERT_EQUAL(otherData2.Tailroom(), 0);
- otherData.TrimBack(2);
- otherData.TrimFront(1);
- UNIT_ASSERT_EQUAL(otherData.data(), otherData2.data());
- data.GrowFront(5);
- data.GrowBack(5);
- UNIT_ASSERT_EQUAL(data.data() + 6, otherData2.data());
- UNIT_ASSERT_EQUAL(data.data() + 6, otherData.data());
- otherData.GrowFront(1);
- UNIT_ASSERT_UNEQUAL(data.data() + 7, otherData.data());
- otherData2.GrowBack(1);
- UNIT_ASSERT_UNEQUAL(data.data() + 6, otherData2.data());
- data = TRcBuf::Uninitialized(10);
- otherData = data;
- data.TrimBack(5);
- UNIT_ASSERT_EQUAL(data.data(), otherData.data());
- UNIT_ASSERT_EQUAL(data.size(), 5);
- }
-
- Y_UNIT_TEST(SliceUnshare) {
- TRcBuf data = TRcBuf::Uninitialized(10, 20, 30);
- TRcBuf otherData(TRcBuf::Piece, data.data() + 1, data.size() - 2, data);
- UNIT_ASSERT_EQUAL(otherData.Headroom(), 0);
- UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0);
- }
-
- Y_UNIT_TEST(Reserve) {
- TRcBuf data = TRcBuf::Copy("test", 4, 5, 6);
- TRcBuf data2 = data;
- data.reserve(1);
- data.ReserveTailroom(6);
- UNIT_ASSERT_EQUAL(data.GetData(), data2.GetData());
- UNIT_ASSERT_EQUAL(data.GetSize(), data2.GetSize());
- UNIT_ASSERT_EQUAL(data.Tailroom(), 6);
- data.ReserveHeadroom(5);
- UNIT_ASSERT_EQUAL(data.GetData(), data2.GetData());
- UNIT_ASSERT_EQUAL(data.GetSize(), data2.GetSize());
- UNIT_ASSERT_EQUAL(data.Headroom(), 5);
- data.ReserveBidi(5, 6);
- UNIT_ASSERT_EQUAL(data.GetData(), data2.GetData());
- UNIT_ASSERT_EQUAL(data.GetSize(), data2.GetSize());
- UNIT_ASSERT_EQUAL(data.Headroom(), 5);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 6);
- data.ReserveHeadroom(6);
- UNIT_ASSERT_EQUAL(data.Headroom(), 6);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 6);
- UNIT_ASSERT_EQUAL(::memcmp(data.GetData(), "test", 4), 0);
- data.ReserveTailroom(7);
- UNIT_ASSERT_EQUAL(data.Headroom(), 6);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 7);
- UNIT_ASSERT_EQUAL(::memcmp(data.GetData(), "test", 4), 0);
- data.ReserveBidi(7, 8);
- UNIT_ASSERT_EQUAL(data.Headroom(), 7);
- UNIT_ASSERT_EQUAL(data.Tailroom(), 8);
- UNIT_ASSERT_EQUAL(::memcmp(data.GetData(), "test", 4), 0);
- }
-}
diff --git a/library/cpp/actors/util/recentwnd.h b/library/cpp/actors/util/recentwnd.h
deleted file mode 100644
index 0f5ee17fa0..0000000000
--- a/library/cpp/actors/util/recentwnd.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#pragma once
-
-#include <util/generic/deque.h>
-
-template <typename TElem,
- template <typename, typename...> class TContainer = TDeque>
-class TRecentWnd {
-public:
- TRecentWnd(ui32 wndSize)
- : MaxWndSize_(wndSize)
- {
- }
-
- void Push(const TElem& elem) {
- if (Window_.size() == MaxWndSize_)
- Window_.erase(Window_.begin());
- Window_.emplace_back(elem);
- }
-
- void Push(TElem&& elem) {
- if (Window_.size() == MaxWndSize_)
- Window_.erase(Window_.begin());
- Window_.emplace_back(std::move(elem));
- }
-
- TElem& Last() {
- return Window_.back();
- }
- const TElem& Last() const {
- return Window_.back();
- }
- bool Full() const {
- return Window_.size() == MaxWndSize_;
- }
- ui64 Size() const {
- return Window_.size();
- }
-
- using const_iterator = typename TContainer<TElem>::const_iterator;
-
- const_iterator begin() {
- return Window_.begin();
- }
- const_iterator end() {
- return Window_.end();
- }
-
- void Reset(ui32 wndSize = 0) {
- Window_.clear();
- if (wndSize != 0) {
- MaxWndSize_ = wndSize;
- }
- }
-
- void ResetWnd(ui32 wndSize) {
- Y_ABORT_UNLESS(wndSize != 0);
- MaxWndSize_ = wndSize;
- if (Window_.size() > MaxWndSize_) {
- Window_.erase(Window_.begin(),
- Window_.begin() + Window_.size() - MaxWndSize_);
- }
- }
-
-private:
- TContainer<TElem> Window_;
- ui32 MaxWndSize_;
-};
diff --git a/library/cpp/actors/util/rope.cpp b/library/cpp/actors/util/rope.cpp
deleted file mode 100644
index 0927774099..0000000000
--- a/library/cpp/actors/util/rope.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "rope.h"
-#include <library/cpp/containers/absl_flat_hash/flat_hash_set.h>
-
-size_t TRope::GetOccupiedMemorySize() const {
- size_t res = 0;
- absl::flat_hash_set<const void*> chunks;
- for (const auto& chunk : Chain) {
- if (const auto [it, inserted] = chunks.insert(chunk.Backend.UniqueId()); inserted) {
- res += chunk.Backend.GetOccupiedMemorySize();
- }
- }
- return res;
-}
diff --git a/library/cpp/actors/util/rope.h b/library/cpp/actors/util/rope.h
deleted file mode 100644
index b092d502cd..0000000000
--- a/library/cpp/actors/util/rope.h
+++ /dev/null
@@ -1,1148 +0,0 @@
-#pragma once
-
-#include <util/generic/ptr.h>
-#include <util/generic/string.h>
-#include <util/generic/hash_set.h>
-#include <util/generic/scope.h>
-#include <util/stream/zerocopy.h>
-#include <util/stream/str.h>
-#include <util/system/sanitizers.h>
-#include <util/system/valgrind.h>
-
-// exactly one of them must be included
-#include "rope_cont_embedded_list.h"
-//#include "rope_cont_list.h"
-//#include "rope_cont_deque.h"
-
-#include "rc_buf.h"
-
-class TRopeAlignedBuffer : public IContiguousChunk {
- static constexpr size_t Alignment = 16;
- static constexpr size_t MallocAlignment = sizeof(size_t);
-
- ui32 Size;
- const ui32 Capacity;
- const ui32 Offset;
- alignas(Alignment) char Data[];
-
- TRopeAlignedBuffer(size_t size)
- : Size(size)
- , Capacity(size)
- , Offset((Alignment - reinterpret_cast<uintptr_t>(Data)) & (Alignment - 1))
- {
- Y_ABORT_UNLESS(Offset <= Alignment - MallocAlignment);
- }
-
-public:
- static TIntrusivePtr<TRopeAlignedBuffer> Allocate(size_t size) {
- return new(malloc(sizeof(TRopeAlignedBuffer) + size + Alignment - MallocAlignment)) TRopeAlignedBuffer(size);
- }
-
- void *operator new(size_t) {
- Y_ABORT();
- }
-
- void *operator new(size_t, void *ptr) {
- return ptr;
- }
-
- void operator delete(void *ptr) {
- free(ptr);
- }
-
- void operator delete(void* p, void* ptr) {
- Y_UNUSED(p);
- Y_UNUSED(ptr);
- }
-
- TContiguousSpan GetData() const override {
- return {Data + Offset, Size};
- }
-
- TMutableContiguousSpan GetDataMut() override {
- return {Data + Offset, Size};
- }
-
- size_t GetOccupiedMemorySize() const override {
- return Capacity;
- }
-
- size_t GetCapacity() const {
- return Capacity;
- }
-
- char *GetBuffer() {
- return Data + Offset;
- }
-};
-
-namespace NRopeDetails {
-
- template<bool IsConst, typename TRope, typename TList>
- struct TIteratorTraits;
-
- template<typename TRope, typename TList>
- struct TIteratorTraits<true, TRope, TList> {
- using TRopePtr = const TRope*;
- using TListIterator = typename TList::const_iterator;
- };
-
- template<typename TRope, typename TList>
- struct TIteratorTraits<false, TRope, TList> {
- using TRopePtr = TRope*;
- using TListIterator = typename TList::iterator;
- };
-
-} // NRopeDetails
-
-class TRopeArena;
-
-template<typename T>
-struct always_false : std::false_type {};
-
-class TRope {
- friend class TRopeArena;
-
- using TChunkList = NRopeDetails::TChunkList<TRcBuf>;
-
-private:
- // we use list here to store chain items as we have to keep valid iterators when erase/insert operations are invoked;
- // iterator uses underlying container's iterator, so we have to use container that keeps valid iterators on delete,
- // thus, the list
- TChunkList Chain;
- size_t Size = 0;
-
-private:
- template<bool IsConst>
- class TIteratorImpl {
- using TTraits = NRopeDetails::TIteratorTraits<IsConst, TRope, TChunkList>;
-
- typename TTraits::TRopePtr Rope;
- typename TTraits::TListIterator Iter;
- const char *Ptr; // ptr is always nullptr when iterator is positioned at the rope end
-
-#ifndef NDEBUG
- ui32 ValidityToken;
-#endif
-
- private:
- TIteratorImpl(typename TTraits::TRopePtr rope, typename TTraits::TListIterator iter, const char *ptr = nullptr)
- : Rope(rope)
- , Iter(iter)
- , Ptr(ptr)
-#ifndef NDEBUG
- , ValidityToken(Rope->GetValidityToken())
-#endif
- {}
-
- public:
- TIteratorImpl()
- : Rope(nullptr)
- , Ptr(nullptr)
- {}
-
- template<bool IsOtherConst>
- TIteratorImpl(const TIteratorImpl<IsOtherConst>& other)
- : Rope(other.Rope)
- , Iter(other.Iter)
- , Ptr(other.Ptr)
-#ifndef NDEBUG
- , ValidityToken(other.ValidityToken)
-#endif
- {}
-
- void CheckValid() const {
-#ifndef NDEBUG
- Y_ABORT_UNLESS(ValidityToken == Rope->GetValidityToken());
- Y_ABORT_UNLESS(Iter == Rope->Chain.end() || Iter->Backend);
-#endif
- }
-
- TIteratorImpl& operator +=(size_t amount) {
- CheckValid();
-
- while (amount) {
- Y_DEBUG_ABORT_UNLESS(Valid());
- const size_t max = ContiguousSize();
- const size_t num = std::min(amount, max);
- amount -= num;
- Ptr += num;
- if (Ptr == Iter->End) {
- AdvanceToNextContiguousBlock();
- }
- }
-
- return *this;
- }
-
- TIteratorImpl operator +(size_t amount) const {
- CheckValid();
-
- return TIteratorImpl(*this) += amount;
- }
-
- TIteratorImpl& operator -=(size_t amount) {
- CheckValid();
-
- while (amount) {
- const size_t num = Ptr ? std::min<size_t>(amount, Ptr - Iter->Begin) : 0;
- amount -= num;
- Ptr -= num;
- if (amount) {
- Y_DEBUG_ABORT_UNLESS(Iter != GetChainBegin());
- --Iter;
- Ptr = Iter->End;
- }
- }
-
- return *this;
- }
-
- TIteratorImpl operator -(size_t amount) const {
- CheckValid();
- return TIteratorImpl(*this) -= amount;
- }
-
- std::pair<const char*, size_t> operator *() const {
- return {ContiguousData(), ContiguousSize()};
- }
-
- TIteratorImpl& operator ++() {
- AdvanceToNextContiguousBlock();
- return *this;
- }
-
- TIteratorImpl operator ++(int) const {
- auto it(*this);
- it.AdvanceToNextContiguousBlock();
- return it;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Operation with contiguous data
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- // Get the pointer to the contiguous block of data; valid locations are [Data; Data + Size).
- const char *ContiguousData() const {
- CheckValid();
- return Ptr;
- }
-
- template<bool Mut = !IsConst, std::enable_if_t<Mut, bool> = true>
- char *ContiguousDataMut() {
- CheckValid();
- return GetChunk().GetDataMut();
- }
-
- template<bool Mut = !IsConst, std::enable_if_t<Mut, bool> = true>
- char *UnsafeContiguousDataMut() {
- CheckValid();
- return GetChunk().UnsafeGetDataMut();
- }
-
- // Get the amount of contiguous block.
- size_t ContiguousSize() const {
- CheckValid();
- return Ptr ? Iter->End - Ptr : 0;
- }
-
- size_t ChunkOffset() const {
- return Ptr ? Ptr - Iter->Begin : 0;
- }
-
- // Advance to next contiguous block of data.
- void AdvanceToNextContiguousBlock() {
- CheckValid();
- Y_DEBUG_ABORT_UNLESS(Valid());
- ++Iter;
- Ptr = Iter != GetChainEnd() ? Iter->Begin : nullptr;
- }
-
- // Extract some data and advance. Size is not checked here, to it must be provided valid.
- void ExtractPlainDataAndAdvance(void *buffer, size_t len) {
- CheckValid();
-
- while (len) {
- Y_DEBUG_ABORT_UNLESS(Ptr);
-
- // calculate amount of bytes we need to move
- const size_t max = ContiguousSize();
- const size_t num = std::min(len, max);
-
- // copy data to the buffer and advance buffer pointers
- memcpy(buffer, Ptr, num);
- buffer = static_cast<char*>(buffer) + num;
- len -= num;
-
- // advance iterator itself
- Ptr += num;
- if (Ptr == Iter->End) {
- AdvanceToNextContiguousBlock();
- }
- }
- }
-
- // Checks if the iterator points to the end of the rope or not.
- bool Valid() const {
- CheckValid();
- return Ptr;
- }
-
- template<bool IsOtherConst>
- bool operator ==(const TIteratorImpl<IsOtherConst>& other) const {
- Y_DEBUG_ABORT_UNLESS(Rope == other.Rope);
- CheckValid();
- other.CheckValid();
- return Iter == other.Iter && Ptr == other.Ptr;
- }
-
- template<bool IsOtherConst>
- bool operator !=(const TIteratorImpl<IsOtherConst>& other) const {
- CheckValid();
- other.CheckValid();
- return !(*this == other);
- }
-
- private:
- friend class TRope;
-
- typename TTraits::TListIterator operator ->() const {
- CheckValid();
- return Iter;
- }
-
- const TRcBuf& GetChunk() const {
- CheckValid();
- return *Iter;
- }
-
- template<bool Mut = !IsConst, std::enable_if_t<Mut, bool> = true>
- TRcBuf& GetChunk() {
- CheckValid();
- return *Iter;
- }
-
- typename TTraits::TListIterator GetChainBegin() const {
- CheckValid();
- return Rope->Chain.begin();
- }
-
- typename TTraits::TListIterator GetChainEnd() const {
- CheckValid();
- return Rope->Chain.end();
- }
-
- bool PointsToChunkMiddle() const {
- CheckValid();
- return Ptr && Ptr != Iter->Begin;
- }
- };
-
-public:
-#ifndef NDEBUG
- ui32 ValidityToken = 0;
- ui32 GetValidityToken() const { return ValidityToken; }
- void InvalidateIterators() { ++ValidityToken; }
-#else
- void InvalidateIterators() {}
-#endif
-
-public:
- using TConstIterator = TIteratorImpl<true>;
- using TIterator = TIteratorImpl<false>;
-
-public:
- TRope() = default;
- TRope(const TRope& rope) = default;
-
- TRope(const TRcBuf& data) {
- if(!data.HasBuffer()) {
- return;
- }
- Size = data.GetSize();
- Chain.PutToEnd(data);
- }
-
- TRope(TRcBuf&& data) {
- if(!data.HasBuffer()) {
- return;
- }
- Size = data.GetSize();
- Chain.PutToEnd(std::move(data));
- }
-
- TRope(TRope&& rope)
- : Chain(std::move(rope.Chain))
- , Size(std::exchange(rope.Size, 0))
- {
- rope.InvalidateIterators();
- }
-
- explicit TRope(TString s) {
- if (s) {
- Size = s.size();
- if (s.capacity() < 32) {
- s.reserve(32);
- }
- Chain.PutToEnd(std::move(s));
- }
- }
-
- explicit TRope(NActors::TSharedData s) {
- Size = s.size();
- Chain.PutToEnd(std::move(s));
- }
-
- TRope(IContiguousChunk::TPtr item) {
- Size = item->GetData().size();
- Chain.PutToEnd(std::move(item));
- }
-
- TRope(TConstIterator begin, TConstIterator end) {
- Y_DEBUG_ABORT_UNLESS(begin.Rope == end.Rope);
- if (begin.Rope == this) {
- TRope temp(begin, end);
- *this = std::move(temp);
- return;
- }
-
- while (begin.Iter != end.Iter) {
- const size_t size = begin.ContiguousSize();
- Chain.PutToEnd(TRcBuf::Piece, begin.ContiguousData(), size, begin.GetChunk());
- begin.AdvanceToNextContiguousBlock();
- Size += size;
- }
-
- if (begin != end && end.PointsToChunkMiddle()) {
- Chain.PutToEnd(TRcBuf::Piece, begin.Ptr, end.Ptr, begin.GetChunk());
- Size += end.Ptr - begin.Ptr;
- }
- }
-
- ~TRope() {
- }
-
- // creates a copy of rope with chunks with inefficient storage ratio being copied with arena allocator
- static TRope CopySpaceOptimized(TRope&& origin, size_t worstRatioPer1k, TRopeArena& arena);
-
- TRope& operator=(const TRope& other) {
- Chain = other.Chain;
- Size = other.Size;
- return *this;
- }
-
- TRope& operator=(TRope&& other) {
- Chain = std::move(other.Chain);
- Size = std::exchange(other.Size, 0);
- InvalidateIterators();
- other.InvalidateIterators();
- return *this;
- }
-
- size_t GetSize() const {
- return Size;
- }
-
- size_t size() const {
- return Size;
- }
-
- size_t capacity() const {
- return Size;
- }
-
- bool IsEmpty() const {
- return !Size;
- }
-
- bool empty() const {
- return IsEmpty();
- }
-
- operator bool() const {
- return Chain;
- }
-
- TIterator Begin() {
- return *this ? TIterator(this, Chain.begin(), Chain.GetFirstChunk().Begin) : End();
- }
-
- TIterator End() {
- return TIterator(this, Chain.end());
- }
-
- TIterator Iterator(TChunkList::iterator it) {
- return TIterator(this, it, it != Chain.end() ? it->Begin : nullptr);
- }
-
- TIterator Position(size_t index) {
- return Begin() + index;
- }
-
- TConstIterator Begin() const {
- return *this ? TConstIterator(this, Chain.begin(), Chain.GetFirstChunk().Begin) : End();
- }
-
- TConstIterator End() const {
- return TConstIterator(this, Chain.end());
- }
-
- TConstIterator Position(size_t index) const {
- return Begin() + index;
- }
-
- TConstIterator begin() const { return Begin(); }
- TConstIterator end() const { return End(); }
-
- void Erase(TIterator begin, TIterator end) {
- Cut(begin, end, nullptr);
- }
-
- TRope Extract(TIterator begin, TIterator end) {
- TRope res;
- Cut(begin, end, &res);
- return res;
- }
-
- void ExtractFront(size_t num, TRope *dest) {
- Y_ABORT_UNLESS(Size >= num);
- if (num == Size && !*dest) {
- *dest = std::move(*this);
- return;
- }
- Size -= num;
- dest->Size += num;
-
- TChunkList::iterator first = Chain.begin();
-
- if (num >= first->GetSize() && dest->Chain) { // see if we can glue first chunk to the destination rope
- auto& last = dest->Chain.GetLastChunk();
- if (last.Backend == first->Backend && last.End == first->Begin) {
- last.End = first->End;
- num -= first->GetSize();
- first = Chain.Erase(first);
- }
- }
-
- TChunkList::iterator it;
- for (it = first; num && num >= it->GetSize(); ++it) {
- num -= it->GetSize();
- }
- first = dest->Chain.Splice(dest->Chain.end(), Chain, first, it);
-
- if (num) { // still more data to extract
- if (dest->Chain) {
- auto& last = dest->Chain.GetLastChunk();
- if (last.Backend == first->Backend && last.End == first->Begin) {
- first->Begin += num;
- last.End = first->Begin;
- return;
- }
- }
- dest->Chain.PutToEnd(TRcBuf::Piece, first->Begin, first->Begin + num, *first);
- first->Begin += num;
- }
- }
-
- void Insert(TIterator pos, TRope&& rope) {
- Y_DEBUG_ABORT_UNLESS(this == pos.Rope);
- Y_DEBUG_ABORT_UNLESS(this != &rope);
-
- if (!rope) {
- return; // do nothing for empty rope
- }
-
- // adjust size
- Size += std::exchange(rope.Size, 0);
-
- // check if we have to split the block
- if (pos.PointsToChunkMiddle()) {
- pos.Iter = Chain.InsertBefore(pos.Iter, TRcBuf::Piece, pos->Begin, pos.Ptr, pos.GetChunk());
- ++pos.Iter;
- pos->Begin = pos.Ptr;
- }
-
- // perform glueing if possible
- TRcBuf *ropeLeft = &rope.Chain.GetFirstChunk();
- TRcBuf *ropeRight = &rope.Chain.GetLastChunk();
- bool gluedLeft = false, gluedRight = false;
- if (pos.Iter != Chain.begin()) { // glue left part whenever possible
- // obtain iterator to previous chunk
- auto prev(pos.Iter);
- --prev;
- if (prev->End == ropeLeft->Begin && prev->Backend == ropeLeft->Backend) { // it is glueable
- prev->End = ropeLeft->End;
- gluedLeft = true;
- }
- }
- if (pos.Iter != Chain.end() && ropeRight->End == pos->Begin && ropeRight->Backend == pos->Backend) {
- pos->Begin = ropeRight->Begin;
- gluedRight = true;
- }
- if (gluedLeft) {
- rope.Chain.EraseFront();
- }
- if (gluedRight) {
- if (rope) {
- rope.Chain.EraseBack();
- } else { // it looks like double-glueing for the same chunk, we have to drop previous one
- auto prev(pos.Iter);
- --prev;
- pos->Begin = prev->Begin;
- pos.Iter = Chain.Erase(prev);
- }
- }
- if (rope) { // insert remains
- Chain.Splice(pos.Iter, rope.Chain, rope.Chain.begin(), rope.Chain.end());
- }
- Y_DEBUG_ABORT_UNLESS(!rope);
- InvalidateIterators();
- }
-
- void EraseFront(size_t len) {
- Y_DEBUG_ABORT_UNLESS(Size >= len);
- Size -= len;
-
- while (len) {
- Y_DEBUG_ABORT_UNLESS(Chain);
- TRcBuf& item = Chain.GetFirstChunk();
- const size_t itemSize = item.GetSize();
- if (len >= itemSize) {
- Chain.EraseFront();
- len -= itemSize;
- } else {
- item.Begin += len;
- break;
- }
- }
-
- InvalidateIterators();
- }
-
- void EraseBack(size_t len) {
- Y_DEBUG_ABORT_UNLESS(Size >= len);
- Size -= len;
-
- while (len) {
- Y_DEBUG_ABORT_UNLESS(Chain);
- TRcBuf& item = Chain.GetLastChunk();
- const size_t itemSize = item.GetSize();
- if (len >= itemSize) {
- Chain.EraseBack();
- len -= itemSize;
- } else {
- item.End -= len;
- break;
- }
- }
-
- InvalidateIterators();
- }
-
- bool ExtractFrontPlain(void *buffer, size_t len) {
- // check if we have enough data in the rope
- if (Size < len) {
- return false;
- }
- Size -= len;
- while (len) {
- auto& chunk = Chain.GetFirstChunk();
- Y_DEBUG_ABORT_UNLESS(chunk.Backend);
- const size_t num = Min(len, chunk.GetSize());
- memcpy(buffer, chunk.Begin, num);
- buffer = static_cast<char*>(buffer) + num;
- len -= num;
- chunk.Begin += num;
- if (chunk.Begin == chunk.End) {
- Chain.EraseFront();
- }
- }
- InvalidateIterators();
- return true;
- }
-
- bool FetchFrontPlain(char **ptr, size_t *remain) {
- const size_t num = Min(*remain, Size);
- ExtractFrontPlain(*ptr, num);
- *ptr += num;
- *remain -= num;
- return !*remain;
- }
-
- static int Compare(const TRope& x, const TRope& y) {
- TConstIterator xIter = x.Begin(), yIter = y.Begin();
- while (xIter.Valid() && yIter.Valid()) {
- const size_t step = std::min(xIter.ContiguousSize(), yIter.ContiguousSize());
- if (int res = memcmp(xIter.ContiguousData(), yIter.ContiguousData(), step)) {
- return res;
- }
- xIter += step;
- yIter += step;
- }
- return xIter.Valid() - yIter.Valid();
- }
-
- static int Compare(const TRope& x, const TContiguousSpan& y) {
- TConstIterator xIter = x.Begin();
- const char* yData = y.data();
- size_t yOffset = 0;
- while (xIter.Valid() && yOffset != y.size()) {
- const size_t step = std::min(xIter.ContiguousSize(), y.size() - yOffset);
- if (int res = memcmp(xIter.ContiguousData(), yData + yOffset, step)) {
- return res;
- }
- xIter += step;
- yOffset += step;
- }
- return xIter.Valid() - (yOffset != y.size());
- }
-
- static int Compare(const TContiguousSpan& x, const TRope& y) {
- return -Compare(y, x);
- }
-
- // Use this method carefully -- it may significantly reduce performance when misused.
- TString ConvertToString() const {
- return ExtractUnderlyingContainerOrCopy<TString>();
- }
-
- /**
- * WARN: this method supports extracting only for natively supported types for any other type the data *will* be copied
- */
- template <class TResult>
- TResult ExtractUnderlyingContainerOrCopy() const {
- if (Chain.begin() != Chain.end() && ++Chain.begin() == Chain.end()) {
- return Chain.GetFirstChunk().ExtractUnderlyingContainerOrCopy<TResult>();
- }
-
- const size_t size = GetSize();
- TResult res = TResult::Uninitialized(size);
- char* data = NContiguousDataDetails::TContainerTraits<TResult>::UnsafeGetDataMut(res);
- Begin().ExtractPlainDataAndAdvance(data, size);
- return res;
- }
-
- void clear() {
- Erase(Begin(), End());
- }
-
- bool IsContiguous() const {
- if(Begin() == End() || (++Begin() == End())) {
- return true;
- }
- return false;
- }
-
- void Compact(size_t headroom = 0, size_t tailroom = 0) {
- if(!IsContiguous()) {
- // TODO(innokentii): use better container, when most outer users stop use TString
- TRcBuf res = TRcBuf::Uninitialized(GetSize(), headroom, tailroom);
- Begin().ExtractPlainDataAndAdvance(res.UnsafeGetDataMut(), res.size());
- Erase(Begin(), End());
- Insert(End(), TRope(res));
- }
- }
-
- static TRope Uninitialized(size_t size)
- {
- TRcBuf res = TRcBuf::Uninitialized(size);
- return TRope(res);
- }
-
- /**
- * Compacts data and calls GetData() on undelying container
- * WARN: Will copy if data isn't contiguous
- */
- TContiguousSpan GetContiguousSpan() {
- if(Begin() == End()) {
- return {nullptr, 0};
- }
- Compact();
- return Begin()->GetContiguousSpan();
- }
-
- /**
- * Compacts data and calls GetDataMut() on undelying container
- * WARN: Will copy if data isn't contiguous
- */
- TMutableContiguousSpan GetContiguousSpanMut() {
- if(Begin() == End()) {
- return {nullptr, 0};
- }
- Compact();
- return Begin()->GetContiguousSpanMut();
- }
-
- /**
- * Compacts data and calls UnsafeGetDataMut() on undelying container
- * WARN: Will copy if data isn't contiguous
- * WARN: Even if underlying container is shared - returns reference to its underlying data
- */
- TMutableContiguousSpan UnsafeGetContiguousSpanMut() {
- if(Begin() == End()) {
- return {nullptr, 0};
- }
- Compact();
- return Begin()->UnsafeGetContiguousSpanMut();
- }
-
- TString DebugString() const {
- TStringStream s;
- s << "{Size# " << Size;
- for (const auto& chunk : Chain) {
- const char *data;
- data = chunk.Backend.GetData().data();
- s << " [" << chunk.Begin - data << ", " << chunk.End - data << ")@" << chunk.Backend.UniqueId();
- }
- s << "}";
- return s.Str();
- }
-
- explicit operator TRcBuf() {
- if(GetSize() == 0) {
- return TRcBuf();
- }
- Compact();
- return TRcBuf(Begin().GetChunk());
- }
-
- size_t GetOccupiedMemorySize() const;
-
- friend bool operator==(const TRope& x, const TRope& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TRope& x, const TRope& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TRope& x, const TRope& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TRope& x, const TRope& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TRope& x, const TRope& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TRope& x, const TRope& y) { return Compare(x, y) >= 0; }
-
- friend bool operator==(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TRope& x, const TContiguousSpan& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TRope& x, const TContiguousSpan& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) >= 0; }
-
- friend bool operator==(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TContiguousSpan& x, const TRope& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TContiguousSpan& x, const TRope& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) >= 0; }
-
- // FIXME(innokentii) temporary hack
- friend bool operator==(const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) == 0; }
- friend bool operator!=(const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) != 0; }
- friend bool operator< (const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) < 0; }
- friend bool operator<=(const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) <= 0; }
- friend bool operator> (const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) > 0; }
- friend bool operator>=(const TRope& x, const TRcBuf& y) { return Compare(x, y.GetContiguousSpan()) >= 0; }
-
- friend bool operator==(const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) == 0; }
- friend bool operator!=(const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) != 0; }
- friend bool operator< (const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) < 0; }
- friend bool operator<=(const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) <= 0; }
- friend bool operator> (const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) > 0; }
- friend bool operator>=(const TRcBuf& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) >= 0; }
-
-
-private:
- void Cut(TIterator begin, TIterator end, TRope *target) {
- // ensure all iterators are belong to us
- Y_DEBUG_ABORT_UNLESS(this == begin.Rope && this == end.Rope);
-
- // if begin and end are equal, we do nothing -- checking this case allows us to find out that begin does not
- // point to End(), for example
- if (begin == end) {
- return;
- }
-
- auto addBlock = [&](const TRcBuf& from, const char *begin, const char *end) {
- if (target) {
- target->Chain.PutToEnd(TRcBuf::Piece, begin, end, from);
- target->Size += end - begin;
- }
- Size -= end - begin;
- };
-
- // consider special case -- when begin and end point to the same block; in this case we have to split up this
- // block into two parts
- if (begin.Iter == end.Iter) {
- TRcBuf chunkToSplit = begin.GetChunk();
- addBlock(chunkToSplit, begin.Ptr, end.Ptr);
- const char *firstChunkBegin = begin.PointsToChunkMiddle() ? begin->Begin : nullptr;
- begin->Begin = end.Ptr; // this affects both begin and end iterator pointed values
- if (firstChunkBegin) {
- Chain.InsertBefore(begin.Iter, TRcBuf::Piece, firstChunkBegin, begin.Ptr, chunkToSplit);
- }
- } else {
- // check the first iterator -- if it starts not from the begin of the block, we have to adjust end of the
- // first block to match begin iterator and switch to next block
- if (begin.PointsToChunkMiddle()) {
- addBlock(begin.GetChunk(), begin.Ptr, begin->End);
- begin->End = begin.Ptr;
- begin.AdvanceToNextContiguousBlock();
- }
-
- // now drop full blocks
- size_t rangeSize = 0;
- for (auto it = begin.Iter; it != end.Iter; ++it) {
- Y_DEBUG_ABORT_UNLESS(it->GetSize());
- rangeSize += it->GetSize();
- }
- if (rangeSize) {
- if (target) {
- end.Iter = target->Chain.Splice(target->Chain.end(), Chain, begin.Iter, end.Iter);
- target->Size += rangeSize;
- } else {
- end.Iter = Chain.Erase(begin.Iter, end.Iter);
- }
- Size -= rangeSize;
- }
-
- // and cut the last block if necessary
- if (end.PointsToChunkMiddle()) {
- addBlock(end.GetChunk(), end->Begin, end.Ptr);
- end->Begin = end.Ptr;
- }
- }
-
- InvalidateIterators();
- }
-};
-
-class TRopeArena {
- using TAllocateCallback = std::function<TIntrusivePtr<IContiguousChunk>()>;
-
- TAllocateCallback Allocator;
- TRope Arena;
-
-public:
- TRopeArena(TAllocateCallback&& allocator)
- : Allocator(std::move(allocator))
- {}
-
- TRope CreateRope(const void *buffer, size_t len) {
- TRope res;
-
- while (len) {
- if (Arena) {
- auto iter = Arena.Begin();
- Y_DEBUG_ABORT_UNLESS(iter.Valid());
- char *dest = const_cast<char*>(iter.ContiguousData());
- const size_t bytesToCopy = std::min(len, iter.ContiguousSize());
- memcpy(dest, buffer, bytesToCopy);
- buffer = static_cast<const char*>(buffer) + bytesToCopy;
- len -= bytesToCopy;
- res.Insert(res.End(), Arena.Extract(Arena.Begin(), Arena.Position(bytesToCopy)));
- } else {
- Arena.Insert(Arena.End(), TRope(Allocator()));
- }
- }
-
- // align arena on 8-byte boundary
- const size_t align = 8;
- if (const size_t padding = Arena.GetSize() % align) {
- Arena.EraseFront(padding);
- }
-
- return res;
- }
-};
-
-struct TRopeUtils {
- static void Memset(TRope::TConstIterator dst, char c, size_t size) {
- while (size) {
- Y_DEBUG_ABORT_UNLESS(dst.Valid());
- size_t len = std::min(size, dst.ContiguousSize());
- memset(const_cast<char*>(dst.ContiguousData()), c, len);
- dst += len;
- size -= len;
- }
- }
-
- static void Memcpy(TRope::TConstIterator dst, TRope::TConstIterator src, size_t size) {
- while (size) {
- Y_DEBUG_ABORT_UNLESS(dst.Valid() && src.Valid(),
- "Invalid iterator in memcpy: dst.Valid() - %" PRIu32 ", src.Valid() - %" PRIu32,
- (ui32)dst.Valid(), (ui32)src.Valid());
- size_t len = std::min(size, std::min(dst.ContiguousSize(), src.ContiguousSize()));
- memcpy(const_cast<char*>(dst.ContiguousData()), src.ContiguousData(), len);
- dst += len;
- src += len;
- size -= len;
- }
- }
-
- static void Memcpy(TRope::TConstIterator dst, const char* src, size_t size) {
- while (size) {
- Y_DEBUG_ABORT_UNLESS(dst.Valid());
- size_t len = std::min(size, dst.ContiguousSize());
- memcpy(const_cast<char*>(dst.ContiguousData()), src, len);
- size -= len;
- dst += len;
- src += len;
- }
- }
-
- static void Memcpy(char* dst, TRope::TConstIterator src, size_t size) {
- while (size) {
- Y_DEBUG_ABORT_UNLESS(src.Valid());
- size_t len = std::min(size, src.ContiguousSize());
- memcpy(dst, src.ContiguousData(), len);
- size -= len;
- dst += len;
- src += len;
- }
- }
-
- // copy less or equal to sizeBound bytes, until src is valid
- static size_t SafeMemcpy(char* dst, TRope::TIterator src, size_t sizeBound) {
- size_t origSize = sizeBound;
- while (sizeBound && src.Valid()) {
- size_t len = Min(sizeBound, src.ContiguousSize());
- memcpy(dst, src.ContiguousData(), len);
- sizeBound -= len;
- dst += len;
- src += len;
- }
- return origSize - sizeBound;
- }
-};
-
-template<size_t BLOCK, size_t ALIGN = 16>
-class TRopeSlideView {
- alignas(ALIGN) char Slide[BLOCK]; // use if distance from current point and next chunk is less than BLOCK
- TRope::TIterator Position; // current position at rope
- size_t Size;
- char* Head; // points to data, it might be current rope chunk or Slide
-
-private:
- void FillBlock() {
- size_t chunkSize = Position.ContiguousSize();
- if (chunkSize >= BLOCK) {
- Size = chunkSize;
- Head = const_cast<char*>(Position.ContiguousData());
- } else {
- Size = TRopeUtils::SafeMemcpy(Slide, Position, BLOCK);
- Head = Slide;
- }
- }
-
-public:
- TRopeSlideView(TRope::TIterator position)
- : Position(position)
- {
- FillBlock();
- }
-
- TRopeSlideView(TRope &rope)
- : TRopeSlideView(rope.Begin())
- {}
-
- // if view on slide then copy slide to rope
- void FlushBlock() {
- if (Head == Slide) {
- TRopeUtils::Memcpy(Position, Head, Size);
- }
- }
-
- TRope::TIterator operator+=(size_t amount) {
- Position += amount;
- FillBlock();
- return Position;
- }
-
- TRope::TIterator GetPosition() const {
- return Position;
- }
-
- char* GetHead() const {
- return Head;
- }
-
- ui8* GetUi8Head() const {
- return reinterpret_cast<ui8*>(Head);
- }
-
- size_t ContiguousSize() const {
- return Size;
- }
-
- bool IsOnChunk() const {
- return Head != Slide;
- }
-};
-
-class TRopeZeroCopyInput : public IZeroCopyInput {
- TRope::TConstIterator Iter;
- const char* Data = nullptr;
- size_t Len = 0;
-
-private:
- size_t DoNext(const void** ptr, size_t len) override {
- Y_DEBUG_ABORT_UNLESS(ptr);
- if (Len == 0) {
- if (Iter.Valid()) {
- Data = Iter.ContiguousData();
- Len = Iter.ContiguousSize();
- Y_DEBUG_ABORT_UNLESS(Len);
- Y_DEBUG_ABORT_UNLESS(Data);
- ++Iter;
- } else {
- Data = nullptr;
- }
- }
-
- size_t chunk = std::min(Len, len);
- *ptr = Data;
- Data += chunk;
- Len -= chunk;
- return chunk;
- }
-
-public:
- explicit TRopeZeroCopyInput(TRope::TConstIterator iter)
- : Iter(iter)
- {
- }
-};
-
-inline TRope TRope::CopySpaceOptimized(TRope&& origin, size_t worstRatioPer1k, TRopeArena& arena) {
- TRope res;
- for (TRcBuf& chunk : origin.Chain) {
- size_t ratio = chunk.GetSize() * 1024 / chunk.GetOccupiedMemorySize();
- if (ratio < 1024 - worstRatioPer1k) {
- res.Insert(res.End(), arena.CreateRope(chunk.Begin, chunk.GetSize()));
- } else {
- res.Chain.PutToEnd(std::move(chunk));
- }
- }
- res.Size = origin.Size;
- origin = TRope();
- return res;
-}
-
-
-#if defined(WITH_VALGRIND) || defined(_msan_enabled_)
-
-inline void CheckRopeIsDefined(TRope::TConstIterator begin, ui64 size) {
- while (size) {
- ui64 contiguousSize = Min(size, begin.ContiguousSize());
-# if defined(WITH_VALGRIND)
- VALGRIND_CHECK_MEM_IS_DEFINED(begin.ContiguousData(), contiguousSize);
-# endif
-# if defined(_msan_enabled_)
- NSan::CheckMemIsInitialized(begin.ContiguousData(), contiguousSize);
-# endif
- size -= contiguousSize;
- begin += contiguousSize;
- }
-}
-
-# define CHECK_ROPE_IS_DEFINED(begin, size) CheckRopeIsDefined(begin, size)
-
-#else
-
-# define CHECK_ROPE_IS_DEFINED(begin, size) do {} while (false)
-
-#endif
diff --git a/library/cpp/actors/util/rope_cont_embedded_list.h b/library/cpp/actors/util/rope_cont_embedded_list.h
deleted file mode 100644
index 294599538f..0000000000
--- a/library/cpp/actors/util/rope_cont_embedded_list.h
+++ /dev/null
@@ -1,391 +0,0 @@
-#pragma once
-
-#include <util/generic/intrlist.h>
-
-#include <util/random/random.h>
-
-namespace NRopeDetails {
-
-template<typename TChunk>
-class TChunkList {
- struct TItem : TChunk {
- TItem *Next = nullptr;
- TItem *Prev = nullptr;
-#ifndef NDEBUG
- ui64 ValidityToken = RandomNumber<ui64>();
-#endif
-
- template<typename... TArgs> TItem(TArgs&&... args) : TChunk(std::forward<TArgs>(args)...) {}
-
- ~TItem() {
- Invalidate();
- if (IsInUse()) {
- Unlink();
- }
- }
-
- void LinkBefore(TItem *item) {
- Next = item;
- Prev = item->Prev;
- Next->Prev = Prev->Next = this;
- }
-
- void Unlink() {
- Next->Prev = Prev;
- Prev->Next = Next;
- }
-
- bool IsInUse() const {
- return Next != nullptr;
- }
-
- void ClearSingleItem() {
- Y_DEBUG_ABORT_UNLESS(Next == this && Prev == this);
- static_cast<TChunk&>(*this) = {};
- Next = Prev = nullptr;
- }
-
- template<typename... TArgs>
- TItem *PrepareForUse(TArgs&&... args) {
- Y_DEBUG_ABORT_UNLESS(!IsInUse());
- static_cast<TChunk&>(*this) = TChunk(std::forward<TArgs>(args)...);
- Next = Prev = this;
- Invalidate();
- return this;
- }
-
- static void TransferRange(TItem *insertBefore, TItem *first, TItem *last) { // [first, last] -> insertBefore
- first->Prev->Next = last->Next;
- last->Next->Prev = first->Prev;
- first->Prev = insertBefore->Prev;
- last->Next = insertBefore;
- first->Prev->Next = first;
- last->Next->Prev = last;
- }
-
- void Invalidate() {
-#ifndef NDEBUG
- ValidityToken = RandomNumber<ui64>();
-#endif
- }
- };
-
- // There are three possible states for the list:
- // 1. It is empty. Next = Prev = nullptr, TChunk is default-constructed.
- // 2. It contains single item. Next = Prev = &Root, TChunk contains data.
- // 3. It has more than one item. Next and Prev make up a double-linked list starting with Root item; TChunk contains
- // first item.
- // This container scheme leads to the following properties:
- // 1. Deleting first item in the list invalidates iterators to the first two items.
- // 2. Inserting something before the first item also invalidates iterators to the first two items.
- // This happens because Root is always the first element of the list and when inserting before the Root, we have to
- // shift original Root element to the allocated item and replace Root with newly inserted value.
- // This also makes right-to-left traversing more efficient in some cases.
- TItem Root;
-
- template<typename... TArgs>
- TItem *AllocateItem(TArgs&&... args) {
- return Root.IsInUse()
- ? new TItem{std::forward<TArgs>(args)...}
- : Root.PrepareForUse(std::forward<TArgs>(args)...);
- }
-
-private:
- template<bool IsConst>
- class TIterator {
- friend class TChunkList;
-
- using TChunkListType = std::conditional_t<IsConst, const TChunkList, TChunkList>;
- using TItemType = std::conditional_t<IsConst, const TItem, TItem>;
- using TChunkType = std::conditional_t<IsConst, const TChunk, TChunk>;
-
- TChunkListType *Cont = nullptr;
- TItemType *Item = nullptr;
-#ifndef NDEBUG
- ui64 ValidityToken = 0;
-#endif
-
- private:
- TIterator(TChunkListType *cont, TItemType *item)
- : Cont(cont)
- , Item(item)
- {
- UpdateValidityToken();
- }
-
- public:
- TIterator() = default;
-
- template<bool OtherIsConst, typename = std::enable_if_t<OtherIsConst <= IsConst>>
- TIterator(const TIterator<OtherIsConst>& other)
- : Cont(other.Cont)
- , Item(other.Item)
- {
- UpdateValidityToken();
- }
-
- TChunkType& operator *() const {
- CheckValid();
- return *Item;
- }
-
- TChunkType *operator ->() const {
- CheckValid();
- return Item;
- }
-
- TIterator& operator++() {
- CheckValid();
- Y_DEBUG_ABORT_UNLESS(Item);
- Item = Item->Next;
- if (Item == &Cont->Root) {
- Item = nullptr; // make it end
- }
- UpdateValidityToken();
- return *this;
- }
-
- TIterator operator ++(int) {
- TIterator res(*this);
- ++*this;
- return res;
- }
-
- TIterator& operator--() {
- CheckValid();
- if (!Item) {
- Y_DEBUG_ABORT_UNLESS(*Cont);
- Item = Cont->Root.Prev;
- } else {
- Y_DEBUG_ABORT_UNLESS(Item != &Cont->Root);
- Item = Item->Prev;
- }
- UpdateValidityToken();
- return *this;
- }
-
- TIterator operator --(int) {
- TIterator res(*this);
- --*this;
- return res;
- }
-
- friend bool operator ==(const TIterator& x, const TIterator& y) {
- Y_DEBUG_ABORT_UNLESS(x.Cont == y.Cont);
- x.CheckValid();
- y.CheckValid();
- return x.Item == y.Item;
- }
-
- friend bool operator !=(const TIterator& x, const TIterator& y) {
- return !(x == y);
- }
-
- private:
- void CheckValid() const {
-#ifndef NDEBUG
- Y_DEBUG_ABORT_UNLESS(ValidityToken == (Item ? Item->ValidityToken : 0));
- Y_DEBUG_ABORT_UNLESS(Cont && (Item != &Cont->Root || *Cont));
-#endif
- }
-
- void UpdateValidityToken() {
-#ifndef NDEBUG
- ValidityToken = Item ? Item->ValidityToken : 0;
-#endif
- CheckValid();
- }
- };
-
-public:
- using iterator = TIterator<false>;
- using const_iterator = TIterator<true>;
-
-public:
- TChunkList()
- {}
-
- ~TChunkList() {
- Erase(begin(), end());
- Y_DEBUG_ABORT_UNLESS(!*this);
- }
-
- TChunkList(const TChunkList& other) {
- *this = other;
- }
-
- TChunkList(TChunkList&& other) {
- *this = std::move(other);
- }
-
- TChunkList& operator=(const TChunkList& other) {
- if (this != &other) {
- Erase(begin(), end());
- for (const TChunk& chunk : other) {
- PutToEnd(TChunk(chunk));
- }
- }
- return *this;
- }
-
- TChunkList& operator=(TChunkList&& other) {
- if (this != &other) {
- Erase(begin(), end());
- Y_DEBUG_ABORT_UNLESS(!*this);
- if (other.Root.IsInUse()) { // do we have something to move?
- Root.PrepareForUse(std::move(static_cast<TChunk&>(other.Root)));
- if (other.Root.Next != &other.Root) { // does other contain more than one item?
- TItem::TransferRange(&Root, other.Root.Next, other.Root.Prev);
- }
- other.Root.ClearSingleItem();
- }
- }
- return *this;
- }
-
- template<typename... TArgs>
- void PutToEnd(TArgs&&... args) {
- InsertBefore(end(), std::forward<TArgs>(args)...);
- }
-
- template<typename... TArgs>
- iterator InsertBefore(iterator pos, TArgs&&... args) {
- TItem *item = AllocateItem<TArgs...>(std::forward<TArgs>(args)...);
- if (item == &Root) {
- // this is the first item, we don't do anything about it
- } else if (pos.Item != &Root) {
- item->LinkBefore(pos.Item ? pos.Item : &Root);
- } else {
- item->LinkBefore(Root.Next);
- std::swap(static_cast<TChunk&>(*item), static_cast<TChunk&>(Root));
- item = &Root;
- Root.Invalidate();
- }
- return {this, item};
- }
-
- iterator Erase(iterator pos) {
- Pop(pos);
- return pos;
- }
-
- iterator Erase(iterator first, iterator last) {
- if (first == last) {
- return last;
- }
- for (;;) {
- if (last == begin()) {
- EraseFront();
- return begin();
- } else if (--last == first) {
- return Erase(last);
- } else {
- last = Erase(last);
- }
- }
- }
-
- void EraseFront() {
- PopFront();
- }
-
- void EraseBack() {
- Y_DEBUG_ABORT_UNLESS(*this);
- if (Root.Prev != &Root) {
- delete Root.Prev;
- } else {
- EraseFront();
- }
- }
-
- // Splice moves elements from the 'from' list in the range [first, last) to *this, inserting them before 'pos'. It
- // returns iterator of the next remaining item in the 'from' list.
- iterator Splice(iterator pos, TChunkList& from, iterator first, iterator last) {
- if (first == last) { // the source range is empty
- return last;
- }
-
- const bool fromBegin = first == from.begin();
- if (fromBegin) { // remember we have to transfer the first item before returning
- ++first;
- }
-
- // 'first' here either equals to 'last' or points to the middle of the 'from' list
-
- const bool toBegin = pos == begin();
- if (toBegin && first != last) {
- // we are inserting item to the begin of the list, so move the first item of the range; it is important here
- // that 'last' iterator doesn't get invalidated
- pos = InsertBefore(begin(), from.Pop(first));
- ++pos;
- }
-
- const auto temp = last;
- if (first != last) {
- --last; // set 'last' pointing to the actual last element of the source range
-
- Y_DEBUG_ABORT_UNLESS(first.Item != &from.Root);
- Y_DEBUG_ABORT_UNLESS(pos.Item != &Root);
-
- TItem* const firstItem = first.Item;
- TItem* const lastItem = last.Item;
- TItem* const posItem = pos.Item ? pos.Item : &Root;
-
- TItem::TransferRange(posItem, firstItem, lastItem);
-
- // adjust 'pos' to point to the first inserted item
- pos = {this, firstItem};
- }
-
- if (fromBegin) {
- InsertBefore(toBegin ? begin() : pos, from.PopFront());
- return from.begin();
- } else {
- return temp;
- }
- }
-
- operator bool() const { return Root.IsInUse(); }
-
- TChunk& GetFirstChunk() { Y_DEBUG_ABORT_UNLESS(*this); return Root; }
- const TChunk& GetFirstChunk() const { Y_DEBUG_ABORT_UNLESS(*this); return Root; }
- TChunk& GetLastChunk() { Y_DEBUG_ABORT_UNLESS(*this); return *Root.Prev; }
-
- iterator begin() { return *this ? iterator(this, &Root) : end(); }
- const_iterator begin() const { return *this ? const_iterator(this, &Root) : end(); }
- iterator end() { return {this, nullptr}; }
- const_iterator end() const { return {this, nullptr}; }
-
-private:
- TChunk Pop(iterator& pos) {
- pos.CheckValid();
- Y_DEBUG_ABORT_UNLESS(pos.Item);
-
- if (pos.Item == &Root) {
- TChunk res = PopFront();
- pos = begin();
- return res;
- } else {
- Y_DEBUG_ABORT_UNLESS(pos != end());
- TItem* const item = pos++.Item;
- TChunk res = std::move(static_cast<TChunk&>(*item));
- delete item;
- return res;
- }
- }
-
- TChunk PopFront() {
- Y_DEBUG_ABORT_UNLESS(*this);
- TChunk res = std::move(static_cast<TChunk&>(Root));
- if (Root.Next != &Root) {
- static_cast<TChunk&>(Root) = std::move(static_cast<TChunk&>(*Root.Next));
- delete Root.Next;
- Root.Invalidate();
- } else {
- Root.ClearSingleItem();
- }
- return res;
- }
-};
-
-} // NRopeDetails
diff --git a/library/cpp/actors/util/rope_ut.cpp b/library/cpp/actors/util/rope_ut.cpp
deleted file mode 100644
index 0ff85d6c59..0000000000
--- a/library/cpp/actors/util/rope_ut.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-#include "rope.h"
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-#include "ut_helpers.h"
-
-class TRopeStringBackend : public IContiguousChunk {
- TString Buffer;
-
-public:
- TRopeStringBackend(TString buffer)
- : Buffer(std::move(buffer))
- {}
-
- TContiguousSpan GetData() const override {
- return {Buffer.data(), Buffer.size()};
- }
-
- TMutableContiguousSpan GetDataMut() override {
- return {Buffer.Detach(), Buffer.size()};
- }
-
- TMutableContiguousSpan UnsafeGetDataMut() override {
- return {const_cast<char*>(Buffer.data()), Buffer.size()};
- }
-
- size_t GetOccupiedMemorySize() const override {
- return Buffer.capacity();
- }
-};
-
-TRope CreateRope(TString s, size_t sliceSize) {
- TRope res;
- for (size_t i = 0; i < s.size(); ) {
- size_t len = std::min(sliceSize, s.size() - i);
- if (i % 2) {
- res.Insert(res.End(), TRope(MakeIntrusive<TRopeStringBackend>(s.substr(i, len))));
- } else {
- res.Insert(res.End(), TRope(s.substr(i, len)));
- }
- i += len;
- }
- return res;
-}
-
-TString RopeToString(const TRope& rope) {
- TString res;
- auto iter = rope.Begin();
- while (iter != rope.End()) {
- res.append(iter.ContiguousData(), iter.ContiguousSize());
- iter.AdvanceToNextContiguousBlock();
- }
-
- UNIT_ASSERT_VALUES_EQUAL(rope.GetSize(), res.size());
-
- TString temp = TString::Uninitialized(rope.GetSize());
- rope.Begin().ExtractPlainDataAndAdvance(temp.Detach(), temp.size());
- UNIT_ASSERT_VALUES_EQUAL(temp, res);
-
- return res;
-}
-
-TString Text = "No elements are copied or moved, only the internal pointers of the list nodes are re-pointed.";
-
-Y_UNIT_TEST_SUITE(TRope) {
- Y_UNIT_TEST(StringCompare) {
- TRope rope = CreateRope(Text, 10);
- UNIT_ASSERT_EQUAL(rope, Text);
- UNIT_ASSERT_EQUAL(Text, rope);
- rope.Erase(rope.Begin() + 10, rope.Begin() + 11);
- UNIT_ASSERT_UNEQUAL(rope, Text);
- UNIT_ASSERT_UNEQUAL(Text, rope);
- TString str("aa");
- rope = TRope(TString("ab"));
- UNIT_ASSERT_LT(str, rope);
- UNIT_ASSERT_GT(rope, str);
- str = TString("aa");
- rope = TRope(TString("a"));
- UNIT_ASSERT_LT(rope, str);
- UNIT_ASSERT_GT(str, rope);
- str = TString("a");
- rope = TRope(TString("aa"));
- UNIT_ASSERT_LT(str, rope);
- UNIT_ASSERT_GT(rope, str);
- }
-
- Y_UNIT_TEST(Leak) {
- const size_t begin = 10, end = 20;
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- }
-
- Y_UNIT_TEST(Compacted) {
- TRope rope = CreateRope(Text, 10);
- UNIT_ASSERT_EQUAL(rope.UnsafeGetContiguousSpanMut(), Text);
- UNIT_ASSERT(rope.IsContiguous());
- }
-
-#ifndef TSTRING_IS_STD_STRING
- Y_UNIT_TEST(ExtractZeroCopy) {
- TString str = Text;
- TRope packed(str);
- TString extracted = packed.ExtractUnderlyingContainerOrCopy<TString>();
- UNIT_ASSERT_EQUAL(str.data(), extracted.data());
- }
-
- Y_UNIT_TEST(ExtractZeroCopySlice) {
- TString str = Text;
- TRope sliced(str);
- sliced.EraseFront(1);
- TString extracted = sliced.ExtractUnderlyingContainerOrCopy<TString>();
- UNIT_ASSERT_UNEQUAL(str.data(), extracted.data());
- TRope sliced2(str);
- sliced2.EraseBack(1);
- TString extracted2 = sliced2.ExtractUnderlyingContainerOrCopy<TString>();
- UNIT_ASSERT_UNEQUAL(str.data(), extracted2.data());
- }
-
- Y_UNIT_TEST(TStringDetach) {
- TRope pf;
- TRope rope;
- TString string = TString(Text.data(), Text.size());
- rope = TRope(string);
- pf = rope;
- pf.GetContiguousSpanMut();
- UNIT_ASSERT(!string.IsDetached());
- rope.GetContiguousSpanMut();
- UNIT_ASSERT(string.IsDetached());
- }
-
- Y_UNIT_TEST(TStringUnsafeShared) {
- TRope pf;
- TRope rope;
- TString string = TString(Text.data(), Text.size());
- rope = TRope(string);
- pf = rope;
- UNIT_ASSERT(pf.IsContiguous());
- UNIT_ASSERT_EQUAL(pf.UnsafeGetContiguousSpanMut().data(), string.data());
- UNIT_ASSERT(!string.IsDetached());
- }
-
- Y_UNIT_TEST(ContiguousDataInterop) {
- TString string = "Some long-long text needed for not sharing data and testing";
- TRcBuf data(string);
- UNIT_ASSERT_EQUAL(data.UnsafeGetDataMut(), &(*string.cbegin()));
- TRope rope(data); // check operator TRope
- UNIT_ASSERT_EQUAL(rope.UnsafeGetContiguousSpanMut().data(), &(*string.cbegin()));
- TRcBuf otherData(rope);
- UNIT_ASSERT_EQUAL(otherData.UnsafeGetDataMut(), &(*string.cbegin()));
- TString extractedBack = otherData.ExtractUnderlyingContainerOrCopy<TString>();
- UNIT_ASSERT_EQUAL(extractedBack.data(), &(*string.cbegin()));
- }
-#endif
- Y_UNIT_TEST(CrossCompare) {
- TString str = "some very long string";
- const TString constStr(str);
- TStringBuf strbuf = str;
- const TStringBuf constStrbuf = str;
- TContiguousSpan span(str);
- const TContiguousSpan constSpan(str);
- TMutableContiguousSpan mutableSpan(const_cast<char*>(str.data()), str.size());
- const TMutableContiguousSpan constMutableSpan(const_cast<char*>(str.data()), str.size());
- TRcBuf data(str);
- const TRcBuf constData(str);
- TArrayRef<char> arrRef(const_cast<char*>(str.data()), str.size());
- const TArrayRef<char> constArrRef(const_cast<char*>(str.data()), str.size());
- TArrayRef<const char> arrConstRef(const_cast<char*>(str.data()), str.size());
- const TArrayRef<const char> constArrConstRef(const_cast<char*>(str.data()), str.size());
- NActors::TSharedData sharedData = NActors::TSharedData::Copy(str.data(), str.size());
- const NActors::TSharedData constSharedData(sharedData);
- TRope rope(str);
- const TRope constRope(str);
-
- Permutate(
- [](auto& arg1, auto& arg2) {
- UNIT_ASSERT(arg1 == arg2);
- },
- str,
- constStr,
- strbuf,
- constStrbuf,
- span,
- constSpan,
- mutableSpan,
- constMutableSpan,
- data,
- constData,
- arrRef,
- constArrRef,
- arrConstRef,
- constArrConstRef,
- sharedData,
- constSharedData,
- rope,
- constRope);
- }
-
- Y_UNIT_TEST(BasicRange) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope::TIterator rBegin = rope.Begin() + begin;
- TRope::TIterator rEnd = rope.Begin() + end;
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(rBegin, rEnd)), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(Erase) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- }
- }
- }
-
- Y_UNIT_TEST(Insert) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope part = TRope(rope.Begin() + begin, rope.Begin() + end);
- for (size_t where = 0; where <= Text.size(); ++where) {
- TRope x(rope);
- x.Insert(x.Begin() + where, TRope(part));
- UNIT_ASSERT_VALUES_EQUAL(x.GetSize(), rope.GetSize() + part.GetSize());
- TString text = Text;
- text.insert(text.begin() + where, Text.begin() + begin, Text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(x), text);
- }
- }
- }
- }
-
- Y_UNIT_TEST(Extract) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- TRope part = rope.Extract(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(part), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(EraseFront) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseFront(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(pos));
- }
- }
-
- Y_UNIT_TEST(EraseBack) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseBack(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(0, Text.size() - pos));
- }
- }
-
- Y_UNIT_TEST(ExtractFront) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TRope out;
- while (const size_t len = Min(step, rope.GetSize())) {
- rope.ExtractFront(len, &out);
- UNIT_ASSERT(rope.GetSize() + out.GetSize() == Text.size());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(out), Text.substr(0, out.GetSize()));
- }
- }
- }
-
- Y_UNIT_TEST(ExtractFrontPlain) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TString buffer = Text;
- size_t remain = rope.GetSize();
- while (const size_t len = Min(step, remain)) {
- TString data = TString::Uninitialized(len);
- rope.ExtractFrontPlain(data.Detach(), data.size());
- UNIT_ASSERT_VALUES_EQUAL(data, buffer.substr(0, len));
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), buffer.substr(len));
- buffer = buffer.substr(len);
- remain -= len;
- }
- }
- }
-
- Y_UNIT_TEST(FetchFrontPlain) {
- char s[10];
- char *data = s;
- size_t remain = sizeof(s);
- TRope rope = TRope(TString("HELLO"));
- UNIT_ASSERT(!rope.FetchFrontPlain(&data, &remain));
- UNIT_ASSERT(!rope);
- rope.Insert(rope.End(), TRope(TString("WORLD!!!")));
- UNIT_ASSERT(rope.FetchFrontPlain(&data, &remain));
- UNIT_ASSERT(!remain);
- UNIT_ASSERT(rope.GetSize() == 3);
- UNIT_ASSERT_VALUES_EQUAL(rope.ConvertToString(), "!!!");
- UNIT_ASSERT(!strncmp(s, "HELLOWORLD", 10));
- }
-
- Y_UNIT_TEST(Glueing) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin <= Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TString repr = rope.DebugString();
- TRope temp = rope.Extract(rope.Position(begin), rope.Position(end));
- rope.Insert(rope.Position(begin), std::move(temp));
- UNIT_ASSERT_VALUES_EQUAL(repr, rope.DebugString());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text);
- }
- }
- }
-
- Y_UNIT_TEST(IterWalk) {
- TRope rope = CreateRope(Text, 10);
- for (size_t step1 = 0; step1 <= rope.GetSize(); ++step1) {
- for (size_t step2 = 0; step2 <= step1; ++step2) {
- TRope::TConstIterator iter = rope.Begin();
- iter += step1;
- iter -= step2;
- UNIT_ASSERT(iter == rope.Position(step1 - step2));
- }
- }
- }
-
- Y_UNIT_TEST(Compare) {
- auto check = [](const TString& x, const TString& y) {
- const TRope xRope = CreateRope(x, 7);
- const TRope yRope = CreateRope(y, 11);
- UNIT_ASSERT_VALUES_EQUAL(xRope == yRope, x == y);
- UNIT_ASSERT_VALUES_EQUAL(xRope == y, x == y);
- UNIT_ASSERT_VALUES_EQUAL(x == yRope, x == y);
- UNIT_ASSERT_VALUES_EQUAL(xRope != yRope, x != y);
- UNIT_ASSERT_VALUES_EQUAL(xRope != y, x != y);
- UNIT_ASSERT_VALUES_EQUAL(x != yRope, x != y);
- UNIT_ASSERT_VALUES_EQUAL(xRope < yRope, x < y);
- UNIT_ASSERT_VALUES_EQUAL(xRope < y, x < y);
- UNIT_ASSERT_VALUES_EQUAL(x < yRope, x < y);
- UNIT_ASSERT_VALUES_EQUAL(xRope <= yRope, x <= y);
- UNIT_ASSERT_VALUES_EQUAL(xRope <= y, x <= y);
- UNIT_ASSERT_VALUES_EQUAL(x <= yRope, x <= y);
- UNIT_ASSERT_VALUES_EQUAL(xRope > yRope, x > y);
- UNIT_ASSERT_VALUES_EQUAL(xRope > y, x > y);
- UNIT_ASSERT_VALUES_EQUAL(x > yRope, x > y);
- UNIT_ASSERT_VALUES_EQUAL(xRope >= yRope, x >= y);
- UNIT_ASSERT_VALUES_EQUAL(xRope >= y, x >= y);
- UNIT_ASSERT_VALUES_EQUAL(x >= yRope, x >= y);
- };
-
- TVector<TString> pool;
- for (size_t k = 0; k < 10; ++k) {
- size_t len = RandomNumber<size_t>(100) + 100;
- TString s = TString::Uninitialized(len);
- char *p = s.Detach();
- for (size_t j = 0; j < len; ++j) {
- *p++ = RandomNumber<unsigned char>();
- }
- pool.push_back(std::move(s));
- }
-
- for (const TString& x : pool) {
- for (const TString& y : pool) {
- check(x, y);
- }
- }
- }
-
- Y_UNIT_TEST(RopeZeroCopyInputBasic) {
- TRope rope = CreateRope(Text, 3);
- TRopeZeroCopyInput input(rope.Begin());
-
- TString result;
- TStringOutput output(result);
- TransferData(&input, &output);
- UNIT_ASSERT_EQUAL(result, Text);
- }
-
- Y_UNIT_TEST(RopeZeroCopyInput) {
- TRope rope;
- rope.Insert(rope.End(), TRope{"abc"});
- rope.Insert(rope.End(), TRope{TString{}});
- rope.Insert(rope.End(), TRope{"de"});
- rope.Insert(rope.End(), TRope{TString{}});
- rope.Insert(rope.End(), TRope{TString{}});
- rope.Insert(rope.End(), TRope{"fghi"});
-
- TRopeZeroCopyInput input(rope.Begin());
-
- const char* data = nullptr;
- size_t len;
-
- len = input.Next(&data, 2);
- UNIT_ASSERT_EQUAL("ab", TStringBuf(data, len));
-
- len = input.Next(&data, 3);
- UNIT_ASSERT_EQUAL("c", TStringBuf(data, len));
-
- len = input.Next(&data, 3);
- UNIT_ASSERT_EQUAL("de", TStringBuf(data, len));
-
- len = input.Next(&data);
- UNIT_ASSERT_EQUAL("fghi", TStringBuf(data, len));
-
- len = input.Next(&data);
- UNIT_ASSERT_EQUAL(len, 0);
-
- len = input.Next(&data);
- UNIT_ASSERT_EQUAL(len, 0);
- }
-}
diff --git a/library/cpp/actors/util/shared_data.cpp b/library/cpp/actors/util/shared_data.cpp
deleted file mode 100644
index 51311ce7a3..0000000000
--- a/library/cpp/actors/util/shared_data.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "shared_data.h"
-
-#include "memory_tracker.h"
-
-#include <util/system/sys_alloc.h>
-#include <util/system/sanitizers.h>
-
-namespace NActors {
-
- static constexpr char MemoryLabelSharedData[] = "Tablet/TSharedData/Buffers";
-
- char* TSharedData::Allocate(size_t size) {
- char* data = nullptr;
- if (size > 0) {
- if (size >= MaxDataSize) {
- throw std::length_error("Allocate size overflow");
- }
- auto allocSize = OverheadSize + size;
- char* raw = reinterpret_cast<char*>(y_allocate(allocSize));
-
- auto* privateHeader = reinterpret_cast<TPrivateHeader*>(raw);
- privateHeader->AllocSize = allocSize;
- NActors::NMemory::TLabel<MemoryLabelSharedData>::Add(allocSize);
-
- auto* header = reinterpret_cast<THeader*>(raw + PrivateHeaderSize);
- header->RefCount = 1;
- header->Owner = nullptr;
-
- data = raw + OverheadSize;
- NSan::Poison(data, size);
- }
- return data;
- }
-
- void TSharedData::Deallocate(char* data) noexcept {
- if (data) {
- char* raw = data - OverheadSize;
-
- auto* privateHeader = reinterpret_cast<TPrivateHeader*>(raw);
- NActors::NMemory::TLabel<MemoryLabelSharedData>::Sub(privateHeader->AllocSize);
-
- auto* header = reinterpret_cast<THeader*>(raw + PrivateHeaderSize);
- Y_DEBUG_ABORT_UNLESS(header->Owner == nullptr);
-
- y_deallocate(raw);
- }
- }
-
-}
diff --git a/library/cpp/actors/util/shared_data.h b/library/cpp/actors/util/shared_data.h
deleted file mode 100644
index bd9afb00a5..0000000000
--- a/library/cpp/actors/util/shared_data.h
+++ /dev/null
@@ -1,227 +0,0 @@
-#pragma once
-
-#include <library/cpp/deprecated/atomic/atomic.h>
-
-#include <util/system/types.h>
-#include <util/system/compiler.h>
-#include <util/generic/array_ref.h>
-
-namespace NActors {
-
- class TSharedData {
- public:
- class IOwner {
- public:
- virtual ~IOwner() = default;
-
- virtual void Deallocate(char*) noexcept = 0;
- };
-
- struct TPrivateHeader {
- size_t AllocSize;
- size_t Pad;
- };
-
- static_assert(sizeof(TPrivateHeader) == 16, "TPrivateHeader has an unexpected size");
-
- struct THeader {
- TAtomic RefCount;
- IOwner* Owner;
- };
-
- static_assert(sizeof(THeader) == 16, "THeader has an unexpected size");
-
- enum : size_t {
- PrivateHeaderSize = sizeof(TPrivateHeader),
- HeaderSize = sizeof(THeader),
- OverheadSize = PrivateHeaderSize + HeaderSize,
- MaxDataSize = (std::numeric_limits<size_t>::max() - OverheadSize)
- };
-
- public:
- TSharedData() noexcept
- : Data_(nullptr)
- , Size_(0)
- { }
-
- ~TSharedData() noexcept {
- Release();
- }
-
- TSharedData(const TSharedData& other) noexcept
- : Data_(other.Data_)
- , Size_(other.Size_)
- {
- AddRef();
- }
-
- TSharedData(TSharedData&& other) noexcept
- : Data_(other.Data_)
- , Size_(other.Size_)
- {
- other.Data_ = nullptr;
- other.Size_ = 0;
- }
-
- TSharedData& operator=(const TSharedData& other) noexcept {
- if (this != &other) {
- Release();
- Data_ = other.Data_;
- Size_ = other.Size_;
- AddRef();
- }
- return *this;
- }
-
- TSharedData& operator=(TSharedData&& 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() { Y_DEBUG_ABORT_UNLESS(IsPrivate()); return Data_; }
- Y_FORCE_INLINE char* mutable_begin() { Y_DEBUG_ABORT_UNLESS(IsPrivate()); return Data_; }
- Y_FORCE_INLINE char* mutable_end() { Y_DEBUG_ABORT_UNLESS(IsPrivate()); 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_; }
-
- /**
- * Trims data to the specified size
- * Underlying data is not reallocated
- * Returns trimmed amount in bytes
- */
- size_t TrimBack(size_t size) noexcept {
- size_t trimmed = 0;
- if (Size_ > size) {
- trimmed = Size_ - size;
- if (!size) {
- Release();
- Data_ = nullptr;
- }
- Size_ = size;
- }
- return trimmed;
- }
-
- /**
- * 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 = TSharedData::Copy(data(), size());
- }
- return Data_;
- }
-
- /**
- * Returns a view of underlying data starting with pos and up to len bytes
- */
- TStringBuf Slice(size_t pos = 0, size_t len = -1) const noexcept {
- pos = Min(pos, Size_);
- len = Min(len, Size_ - pos);
- return { Data_ + pos, len };
- }
-
- explicit operator TStringBuf() const noexcept {
- return Slice();
- }
-
- bool IsPrivate() const {
- return Data_ ? IsPrivate(Header()) : true;
- }
-
- bool IsShared() const {
- return !IsPrivate();
- }
-
- TString ToString() const {
- return TString(data(), size());
- }
-
- /**
- * Attach to pre-allocated data with a preceding THeader
- */
- static TSharedData AttachUnsafe(char* data, size_t size) noexcept {
- TSharedData result;
- result.Data_ = data;
- result.Size_ = size;
- return result;
- }
-
- /**
- * Make uninitialized buffer of the specified size
- */
- static TSharedData Uninitialized(size_t size) {
- return AttachUnsafe(Allocate(size), size);
- }
-
- /**
- * Make a copy of the specified data
- */
- static TSharedData Copy(const void* data, size_t size) {
- TSharedData result = Uninitialized(size);
- if (size) {
- ::memcpy(result.Data_, data, size);
- }
- return result;
- }
-
- /**
- * Make a copy of the specified data
- */
- static TSharedData Copy(TArrayRef<const char> data) {
- return Copy(data.data(), data.size());
- }
-
- private:
- Y_FORCE_INLINE THeader* Header() const noexcept {
- Y_DEBUG_ABORT_UNLESS(Data_);
- return reinterpret_cast<THeader*>(Data_ - sizeof(THeader));
- }
-
- 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)) {
- if (auto* owner = header->Owner) {
- owner->Deallocate(Data_);
- } else {
- Deallocate(Data_);
- }
- }
- }
- }
-
- private:
- static char* Allocate(size_t size);
- static void Deallocate(char* data) noexcept;
-
- private:
- char* Data_;
- size_t Size_;
- };
-
-}
diff --git a/library/cpp/actors/util/shared_data_backtracing_owner.h b/library/cpp/actors/util/shared_data_backtracing_owner.h
deleted file mode 100644
index ea479d5fd1..0000000000
--- a/library/cpp/actors/util/shared_data_backtracing_owner.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#pragma once
-
-#include <util/system/sys_alloc.h>
-#include <util/system/backtrace.h>
-
-#include "shared_data.h"
-
-class TBackTracingOwner : public NActors::TSharedData::IOwner {
- using THeader = NActors::TSharedData::THeader;
- using TSelf = TBackTracingOwner;
- using IOwner = NActors::TSharedData::IOwner;
-
- static constexpr size_t PrivateHeaderSize = NActors::TSharedData::PrivateHeaderSize;
- static constexpr size_t HeaderSize = NActors::TSharedData::HeaderSize;
- static constexpr size_t OverheadSize = NActors::TSharedData::OverheadSize;
-
- IOwner* RealOwner = nullptr;
- TBackTrace BackTrace;
- const char* Info;
-public:
-
- static constexpr const char* INFO_FROM_SHARED_DATA = "FROM_SHARED_DATA";
- static constexpr const char* INFO_COPIED_STRING = "COPIED_STRING";
- static constexpr const char* INFO_ALLOC_UNINITIALIZED = "ALLOC_UNINITIALIZED";
- static constexpr const char* INFO_ALLOC_UNINIT_ROOMS = "ALLOC_UNINIT_ROOMS";
-
- 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;
- btOwner->BackTrace.Capture();
- btOwner->Info = info;
- header->RefCount = 1;
- header->Owner = btOwner;
- char* data = raw + OverheadSize;
- return data;
- }
-
- static void FakeOwner(const NActors::TSharedData& data, const char* info = nullptr) {
- THeader* header = Header(data);
- if (header) {
- TSelf* btOwner = new TSelf();
- btOwner->BackTrace.Capture();
- btOwner->Info = info;
- if (header->Owner) {
- btOwner->RealOwner = header->Owner;
- }
- header->Owner = btOwner;
- }
- }
-
- static void UnsafePrintBackTrace(NActors::TSharedData& data) {
- THeader* header = Header(data);
- if(header->Owner) {
- TSelf* owner = static_cast<TSelf*>(header->Owner);
- owner->PrintBackTrace();
- }
- }
-
- void Deallocate(char* data) noexcept override {
- if (!RealOwner) {
- char* raw = data - OverheadSize;
- y_deallocate(raw);
- } else {
- RealOwner->Deallocate(data);
- }
-
- delete this;
- }
-
- IOwner* GetRealOwner() const {
- return RealOwner;
- }
-
- void PrintBackTrace() {
- Cerr << "Deallocate TSharedData with info# " << Info << Endl;
- BackTrace.PrintTo(Cerr);
- }
-private:
- static Y_FORCE_INLINE THeader* Header(const NActors::TSharedData& d) noexcept {
- char* data = const_cast<char*>(d.data());
- if (data) {
- return reinterpret_cast<THeader*>(data - HeaderSize);
- } else {
- return nullptr;
- }
- }
-};
diff --git a/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp b/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
deleted file mode 100644
index 4939403454..0000000000
--- a/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-#include <library/cpp/actors/util/rope.h>
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-
-#include "shared_data_rope_backend.h"
-
-namespace NActors {
-
- namespace {
-
- TRope CreateRope(TString s, size_t sliceSize) {
- TRope res;
- for (size_t i = 0; i < s.size(); ) {
- size_t len = std::min(sliceSize, s.size() - i);
- if (i % 2) {
- auto str = s.substr(i, len);
- res.Insert(res.End(), TRope(
- TSharedData::Copy(str.data(), str.size())));
- } else {
- res.Insert(res.End(), TRope(s.substr(i, len)));
- }
- i += len;
- }
- return res;
- }
-
- TString RopeToString(const TRope& rope) {
- TString res;
- auto iter = rope.Begin();
- while (iter != rope.End()) {
- res.append(iter.ContiguousData(), iter.ContiguousSize());
- iter.AdvanceToNextContiguousBlock();
- }
-
- UNIT_ASSERT_VALUES_EQUAL(rope.GetSize(), res.size());
-
- TString temp = TString::Uninitialized(rope.GetSize());
- rope.Begin().ExtractPlainDataAndAdvance(temp.Detach(), temp.size());
- UNIT_ASSERT_VALUES_EQUAL(temp, res);
-
- return res;
- }
-
- TString Text = "No elements are copied or moved, only the internal pointers of the list nodes are re-pointed.";
-
- }
-
- Y_UNIT_TEST_SUITE(TRopeSharedDataNativeBackend) {
-
- // Same tests as in TRope but with new CreateRope using TSharedData backend
-
- Y_UNIT_TEST(Leak) {
- const size_t begin = 10, end = 20;
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- }
-
- Y_UNIT_TEST(BasicRange) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope::TIterator rBegin = rope.Begin() + begin;
- TRope::TIterator rEnd = rope.Begin() + end;
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(rBegin, rEnd)), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(Erase) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- }
- }
- }
-
- Y_UNIT_TEST(Insert) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope part = TRope(rope.Begin() + begin, rope.Begin() + end);
- for (size_t where = 0; where <= Text.size(); ++where) {
- TRope x(rope);
- x.Insert(x.Begin() + where, TRope(part));
- UNIT_ASSERT_VALUES_EQUAL(x.GetSize(), rope.GetSize() + part.GetSize());
- TString text = Text;
- text.insert(text.begin() + where, Text.begin() + begin, Text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(x), text);
- }
- }
- }
- }
-
- Y_UNIT_TEST(Extract) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- TRope part = rope.Extract(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(part), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(EraseFront) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseFront(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(pos));
- }
- }
-
- Y_UNIT_TEST(EraseBack) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseBack(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(0, Text.size() - pos));
- }
- }
-
- Y_UNIT_TEST(ExtractFront) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TRope out;
- while (const size_t len = Min(step, rope.GetSize())) {
- rope.ExtractFront(len, &out);
- UNIT_ASSERT(rope.GetSize() + out.GetSize() == Text.size());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(out), Text.substr(0, out.GetSize()));
- }
- }
- }
-
- Y_UNIT_TEST(ExtractFrontPlain) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TString buffer = Text;
- auto it = rope.Begin();
- size_t remain = rope.GetSize();
- while (const size_t len = Min(step, remain)) {
- TString data = TString::Uninitialized(len);
- it.ExtractPlainDataAndAdvance(data.Detach(), data.size());
- UNIT_ASSERT_VALUES_EQUAL(data, buffer.substr(0, len));
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(it, rope.End())), buffer.substr(len));
- buffer = buffer.substr(len);
- remain -= len;
- }
- }
- }
-
- Y_UNIT_TEST(Glueing) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin <= Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TString repr = rope.DebugString();
- TRope temp = rope.Extract(rope.Position(begin), rope.Position(end));
- rope.Insert(rope.Position(begin), std::move(temp));
- UNIT_ASSERT_VALUES_EQUAL(repr, rope.DebugString());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text);
- }
- }
- }
-
- Y_UNIT_TEST(IterWalk) {
- TRope rope = CreateRope(Text, 10);
- for (size_t step1 = 0; step1 <= rope.GetSize(); ++step1) {
- for (size_t step2 = 0; step2 <= step1; ++step2) {
- TRope::TConstIterator iter = rope.Begin();
- iter += step1;
- iter -= step2;
- UNIT_ASSERT(iter == rope.Position(step1 - step2));
- }
- }
- }
-
- Y_UNIT_TEST(Compare) {
- auto check = [](const TString& x, const TString& y) {
- const TRope xRope = CreateRope(x, 7);
- const TRope yRope = CreateRope(y, 11);
- UNIT_ASSERT_VALUES_EQUAL(xRope == yRope, x == y);
- UNIT_ASSERT_VALUES_EQUAL(xRope != yRope, x != y);
- UNIT_ASSERT_VALUES_EQUAL(xRope < yRope, x < y);
- UNIT_ASSERT_VALUES_EQUAL(xRope <= yRope, x <= y);
- UNIT_ASSERT_VALUES_EQUAL(xRope > yRope, x > y);
- UNIT_ASSERT_VALUES_EQUAL(xRope >= yRope, x >= y);
- };
-
- TVector<TString> pool;
- for (size_t k = 0; k < 10; ++k) {
- size_t len = RandomNumber<size_t>(100) + 100;
- TString s = TString::Uninitialized(len);
- char *p = s.Detach();
- for (size_t j = 0; j < len; ++j) {
- *p++ = RandomNumber<unsigned char>();
- }
- pool.push_back(std::move(s));
- }
-
- for (const TString& x : pool) {
- for (const TString& y : pool) {
- check(x, y);
- }
- }
- }
-
- // Specific TSharedDataRopeBackend tests
-
- Y_UNIT_TEST(RopeOnlyBorrows) {
- TSharedData data = TSharedData::Copy(Text.data(), Text.size());
- {
- TRope rope;
- rope.Insert(rope.End(), TRope(data));
- UNIT_ASSERT(data.IsShared());
- TSharedData dataCopy = data;
- UNIT_ASSERT(dataCopy.IsShared());
- UNIT_ASSERT_EQUAL(dataCopy.data(), data.data());
- rope.Insert(rope.End(), TRope(data));
- rope.Insert(rope.End(), TRope(data));
- dataCopy.TrimBack(10);
- UNIT_ASSERT_EQUAL(rope.GetSize(), data.size() * 3);
- }
- UNIT_ASSERT(data.IsPrivate());
- }
- }
-
-} // namespace NActors
diff --git a/library/cpp/actors/util/shared_data_rope_backend.h b/library/cpp/actors/util/shared_data_rope_backend.h
deleted file mode 100644
index a221ae668b..0000000000
--- a/library/cpp/actors/util/shared_data_rope_backend.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include <library/cpp/actors/util/rc_buf.h>
-
-#include "shared_data.h"
-
-namespace NActors {
-
-class TRopeSharedDataBackend : public IContiguousChunk {
- TSharedData Buffer;
-
-public:
- TRopeSharedDataBackend(TSharedData buffer)
- : Buffer(std::move(buffer))
- {}
-
- TContiguousSpan GetData() const override {
- return {Buffer.data(), Buffer.size()};
- }
-
- TMutableContiguousSpan GetDataMut() override {
- if(Buffer.IsShared()) {
- Buffer = TSharedData::Copy(Buffer.data(), Buffer.size());
- }
- return {Buffer.mutable_data(), Buffer.size()};
- }
-
- TMutableContiguousSpan UnsafeGetDataMut() override {
- return {const_cast<char *>(Buffer.data()), Buffer.size()};
- }
-
- bool IsPrivate() const override {
- return Buffer.IsPrivate();
- }
-
- size_t GetOccupiedMemorySize() const override {
- return Buffer.size();
- }
-};
-
-} // namespace NActors
diff --git a/library/cpp/actors/util/shared_data_rope_backend_ut.cpp b/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
deleted file mode 100644
index b2b4e04634..0000000000
--- a/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-#include <library/cpp/actors/util/rope.h>
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-
-#include "shared_data_rope_backend.h"
-
-namespace NActors {
-
- namespace {
-
- TRope CreateRope(TString s, size_t sliceSize) {
- TRope res;
- for (size_t i = 0; i < s.size(); ) {
- size_t len = std::min(sliceSize, s.size() - i);
- if (i % 2) {
- auto str = s.substr(i, len);
- res.Insert(res.End(), TRope(MakeIntrusive<TRopeSharedDataBackend>(
- TSharedData::Copy(str.data(), str.size()))));
- } else {
- res.Insert(res.End(), TRope(s.substr(i, len)));
- }
- i += len;
- }
- return res;
- }
-
- TString RopeToString(const TRope& rope) {
- TString res;
- auto iter = rope.Begin();
- while (iter != rope.End()) {
- res.append(iter.ContiguousData(), iter.ContiguousSize());
- iter.AdvanceToNextContiguousBlock();
- }
-
- UNIT_ASSERT_VALUES_EQUAL(rope.GetSize(), res.size());
-
- TString temp = TString::Uninitialized(rope.GetSize());
- rope.Begin().ExtractPlainDataAndAdvance(temp.Detach(), temp.size());
- UNIT_ASSERT_VALUES_EQUAL(temp, res);
-
- return res;
- }
-
- TString Text = "No elements are copied or moved, only the internal pointers of the list nodes are re-pointed.";
-
- }
-
- Y_UNIT_TEST_SUITE(TRopeSharedDataBackend) {
-
- // Same tests as in TRope but with new CreateRope using TSharedData backend
-
- Y_UNIT_TEST(Leak) {
- const size_t begin = 10, end = 20;
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- }
-
- Y_UNIT_TEST(BasicRange) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope::TIterator rBegin = rope.Begin() + begin;
- TRope::TIterator rEnd = rope.Begin() + end;
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(rBegin, rEnd)), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(Erase) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- rope.Erase(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- }
- }
- }
-
- Y_UNIT_TEST(Insert) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope part = TRope(rope.Begin() + begin, rope.Begin() + end);
- for (size_t where = 0; where <= Text.size(); ++where) {
- TRope x(rope);
- x.Insert(x.Begin() + where, TRope(part));
- UNIT_ASSERT_VALUES_EQUAL(x.GetSize(), rope.GetSize() + part.GetSize());
- TString text = Text;
- text.insert(text.begin() + where, Text.begin() + begin, Text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(x), text);
- }
- }
- }
- }
-
- Y_UNIT_TEST(Extract) {
- for (size_t begin = 0; begin < Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TRope rope = CreateRope(Text, 10);
- TRope part = rope.Extract(rope.Begin() + begin, rope.Begin() + end);
- TString text = Text;
- text.erase(text.begin() + begin, text.begin() + end);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(part), Text.substr(begin, end - begin));
- }
- }
- }
-
- Y_UNIT_TEST(EraseFront) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseFront(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(pos));
- }
- }
-
- Y_UNIT_TEST(EraseBack) {
- for (size_t pos = 0; pos <= Text.size(); ++pos) {
- TRope rope = CreateRope(Text, 10);
- rope.EraseBack(pos);
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(0, Text.size() - pos));
- }
- }
-
- Y_UNIT_TEST(ExtractFront) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TRope out;
- while (const size_t len = Min(step, rope.GetSize())) {
- rope.ExtractFront(len, &out);
- UNIT_ASSERT(rope.GetSize() + out.GetSize() == Text.size());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(out), Text.substr(0, out.GetSize()));
- }
- }
- }
-
- Y_UNIT_TEST(ExtractFrontPlain) {
- for (size_t step = 1; step <= Text.size(); ++step) {
- TRope rope = CreateRope(Text, 10);
- TString buffer = Text;
- auto it = rope.Begin();
- size_t remain = rope.GetSize();
- while (const size_t len = Min(step, remain)) {
- TString data = TString::Uninitialized(len);
- it.ExtractPlainDataAndAdvance(data.Detach(), data.size());
- UNIT_ASSERT_VALUES_EQUAL(data, buffer.substr(0, len));
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(it, rope.End())), buffer.substr(len));
- buffer = buffer.substr(len);
- remain -= len;
- }
- }
- }
-
- Y_UNIT_TEST(Glueing) {
- TRope rope = CreateRope(Text, 10);
- for (size_t begin = 0; begin <= Text.size(); ++begin) {
- for (size_t end = begin; end <= Text.size(); ++end) {
- TString repr = rope.DebugString();
- TRope temp = rope.Extract(rope.Position(begin), rope.Position(end));
- rope.Insert(rope.Position(begin), std::move(temp));
- UNIT_ASSERT_VALUES_EQUAL(repr, rope.DebugString());
- UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text);
- }
- }
- }
-
- Y_UNIT_TEST(IterWalk) {
- TRope rope = CreateRope(Text, 10);
- for (size_t step1 = 0; step1 <= rope.GetSize(); ++step1) {
- for (size_t step2 = 0; step2 <= step1; ++step2) {
- TRope::TConstIterator iter = rope.Begin();
- iter += step1;
- iter -= step2;
- UNIT_ASSERT(iter == rope.Position(step1 - step2));
- }
- }
- }
-
- Y_UNIT_TEST(Compare) {
- auto check = [](const TString& x, const TString& y) {
- const TRope xRope = CreateRope(x, 7);
- const TRope yRope = CreateRope(y, 11);
- UNIT_ASSERT_VALUES_EQUAL(xRope == yRope, x == y);
- UNIT_ASSERT_VALUES_EQUAL(xRope != yRope, x != y);
- UNIT_ASSERT_VALUES_EQUAL(xRope < yRope, x < y);
- UNIT_ASSERT_VALUES_EQUAL(xRope <= yRope, x <= y);
- UNIT_ASSERT_VALUES_EQUAL(xRope > yRope, x > y);
- UNIT_ASSERT_VALUES_EQUAL(xRope >= yRope, x >= y);
- };
-
- TVector<TString> pool;
- for (size_t k = 0; k < 10; ++k) {
- size_t len = RandomNumber<size_t>(100) + 100;
- TString s = TString::Uninitialized(len);
- char *p = s.Detach();
- for (size_t j = 0; j < len; ++j) {
- *p++ = RandomNumber<unsigned char>();
- }
- pool.push_back(std::move(s));
- }
-
- for (const TString& x : pool) {
- for (const TString& y : pool) {
- check(x, y);
- }
- }
- }
-
- // Specific TSharedDataRopeBackend tests
-
- Y_UNIT_TEST(RopeOnlyBorrows) {
- TSharedData data = TSharedData::Copy(Text.data(), Text.size());
- {
- TRope rope;
- rope.Insert(rope.End(), TRope(MakeIntrusive<TRopeSharedDataBackend>(data)));
- UNIT_ASSERT(data.IsShared());
- TSharedData dataCopy = data;
- UNIT_ASSERT(dataCopy.IsShared());
- UNIT_ASSERT_EQUAL(dataCopy.data(), data.data());
- rope.Insert(rope.End(), TRope(MakeIntrusive<TRopeSharedDataBackend>(data)));
- rope.Insert(rope.End(), TRope(MakeIntrusive<TRopeSharedDataBackend>(data)));
- dataCopy.TrimBack(10);
- UNIT_ASSERT_EQUAL(rope.GetSize(), data.size() * 3);
- }
- UNIT_ASSERT(data.IsPrivate());
- }
- }
-
-} // namespace NActors
diff --git a/library/cpp/actors/util/shared_data_ut.cpp b/library/cpp/actors/util/shared_data_ut.cpp
deleted file mode 100644
index 2f7dc2ccc8..0000000000
--- a/library/cpp/actors/util/shared_data_ut.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-#include "shared_data.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-
-#include <util/generic/hash.h>
-#include <util/generic/deque.h>
-#include <util/system/sys_alloc.h>
-
-namespace NActors {
-
- Y_UNIT_TEST_SUITE(TSharedDataTest) {
-
- Y_UNIT_TEST(BasicBehavior) {
- auto data = TSharedData::Copy("Hello", 5);
- UNIT_ASSERT(data.IsPrivate());
- UNIT_ASSERT(!data.IsShared());
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 5u);
- UNIT_ASSERT_VALUES_EQUAL(data.end() - data.begin(), 5u);
- UNIT_ASSERT_VALUES_EQUAL(data.mutable_end() - data.mutable_begin(), 5u);
- UNIT_ASSERT(data.begin() == data.data());
- UNIT_ASSERT(data.mutable_data() == data.data());
- UNIT_ASSERT(data.mutable_begin() == data.mutable_data());
-
- UNIT_ASSERT_VALUES_EQUAL(data.ToString(), TString("Hello"));
- UNIT_ASSERT_VALUES_EQUAL(::memcmp(data.data(), "Hello", 5), 0);
-
- auto link = data;
- UNIT_ASSERT(!link.IsPrivate());
- UNIT_ASSERT(!data.IsPrivate());
- UNIT_ASSERT(link.IsShared());
- UNIT_ASSERT(data.IsShared());
- UNIT_ASSERT(link.data() == data.data());
- UNIT_ASSERT(link.size() == data.size());
-
- link = { };
- UNIT_ASSERT(link.IsPrivate());
- UNIT_ASSERT(data.IsPrivate());
- UNIT_ASSERT(!link.IsShared());
- UNIT_ASSERT(!data.IsShared());
-
- UNIT_ASSERT_VALUES_EQUAL(TString(TStringBuf(data)), TString("Hello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice()), TString("Hello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1)), TString("ello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 3)), TString("ell"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 100)), TString("ello"));
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(0, 4)), TString("Hell"));
-
- link = data;
- UNIT_ASSERT(link.data() == data.data());
- UNIT_ASSERT_VALUES_UNEQUAL(link.Detach(), data.data());
- UNIT_ASSERT_EQUAL(data.size(), link.size());
- UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice()), TString(link.Slice()));
- }
-
- Y_UNIT_TEST(TrimBehavior) {
- auto data = TSharedData::Uninitialized(42);
-
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u);
- UNIT_ASSERT(data.data() != nullptr);
-
- // Trim to non-zero does not change addresses
- const char* ptr1 = data.data();
- data.TrimBack(31);
- const char* ptr2 = data.data();
-
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 31u);
- UNIT_ASSERT(ptr1 == ptr2);
-
- // Trim to zero releases underlying data
- data.TrimBack(0);
-
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u);
- UNIT_ASSERT(data.data() == nullptr);
- }
-
- class TCustomOwner : public TSharedData::IOwner {
- using THeader = TSharedData::THeader;
-
- public:
- TSharedData Allocate(size_t size) {
- char* raw = reinterpret_cast<char*>(y_allocate(sizeof(THeader) + size));
- THeader* header = reinterpret_cast<THeader*>(raw);
- header->RefCount = 1;
- header->Owner = this;
- char* data = raw + sizeof(THeader);
- Y_ABORT_UNLESS(Allocated_.insert(data).second);
- return TSharedData::AttachUnsafe(data, size);
- }
-
- void Deallocate(char* data) noexcept {
- Y_ABORT_UNLESS(Allocated_.erase(data) > 0);
- char* raw = data - sizeof(THeader);
- y_deallocate(raw);
- Deallocated_.push_back(data);
- }
-
- char* NextDeallocated() {
- char* result = nullptr;
- if (Deallocated_) {
- result = Deallocated_.front();
- Deallocated_.pop_front();
- }
- return result;
- }
-
- private:
- THashSet<void*> Allocated_;
- TDeque<char*> Deallocated_;
- };
-
- Y_UNIT_TEST(CustomOwner) {
- TCustomOwner owner;
- const char* ptr;
-
- // Test destructor releases data
- {
- auto data = owner.Allocate(42);
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u);
- ptr = data.data();
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- // Test assignment releases data
- {
- auto data = owner.Allocate(42);
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u);
- ptr = data.data();
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- data = { };
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- // Test copies keep references correctly
- {
- auto data = owner.Allocate(42);
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u);
- ptr = data.data();
- auto copy = data;
- UNIT_ASSERT_VALUES_EQUAL(copy.size(), 42u);
- UNIT_ASSERT(copy.data() == ptr);
- data = { };
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u);
- UNIT_ASSERT(data.data() == nullptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- // Test assignment releases correct data
- {
- auto data1 = owner.Allocate(42);
- UNIT_ASSERT_VALUES_EQUAL(data1.size(), 42u);
- auto data2 = owner.Allocate(31);
- UNIT_ASSERT_VALUES_EQUAL(data2.size(), 31u);
- ptr = data1.data();
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- data1 = data2;
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- ptr = data2.data();
- UNIT_ASSERT_VALUES_EQUAL(data1.size(), 31u);
- UNIT_ASSERT(data1.data() == ptr);
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- // Test moves don't produce dangling references
- {
- auto data = owner.Allocate(42);
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u);
- ptr = data.data();
- auto moved = std::move(data);
- UNIT_ASSERT_VALUES_EQUAL(moved.size(), 42u);
- UNIT_ASSERT(moved.data() == ptr);
- UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u);
- UNIT_ASSERT(data.data() == nullptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- // Test Detach copies correctly and doesn't affect owned data
- {
- auto data = owner.Allocate(42);
- auto disowned = data;
- disowned.Detach();
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
- }
-
- UNIT_ASSERT(owner.NextDeallocated() == ptr);
- UNIT_ASSERT(owner.NextDeallocated() == nullptr);
-
- }
-
- }
-
-}
diff --git a/library/cpp/actors/util/should_continue.cpp b/library/cpp/actors/util/should_continue.cpp
deleted file mode 100644
index 258e6a0aff..0000000000
--- a/library/cpp/actors/util/should_continue.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "should_continue.h"
-
-void TProgramShouldContinue::ShouldRestart() {
- AtomicSet(State, Restart);
-}
-
-void TProgramShouldContinue::ShouldStop(int returnCode) {
- AtomicSet(ReturnCode, returnCode);
- AtomicSet(State, Stop);
-}
-
-TProgramShouldContinue::EState TProgramShouldContinue::PollState() {
- return static_cast<EState>(AtomicGet(State));
-}
-
-int TProgramShouldContinue::GetReturnCode() {
- return static_cast<int>(AtomicGet(ReturnCode));
-}
-
-void TProgramShouldContinue::Reset() {
- AtomicSet(ReturnCode, 0);
- AtomicSet(State, Continue);
-}
diff --git a/library/cpp/actors/util/should_continue.h b/library/cpp/actors/util/should_continue.h
deleted file mode 100644
index 76acc40dc4..0000000000
--- a/library/cpp/actors/util/should_continue.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "defs.h"
-
-class TProgramShouldContinue {
-public:
- enum EState {
- Continue,
- Stop,
- Restart,
- };
-
- void ShouldRestart();
- void ShouldStop(int returnCode = 0);
-
- EState PollState();
- int GetReturnCode();
-
- void Reset();
-private:
- TAtomic ReturnCode = 0;
- TAtomic State = Continue;
-};
diff --git a/library/cpp/actors/util/thread.h b/library/cpp/actors/util/thread.h
deleted file mode 100644
index d742c8c585..0000000000
--- a/library/cpp/actors/util/thread.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include <util/generic/strbuf.h>
-#include <util/stream/str.h>
-#include <util/system/execpath.h>
-#include <util/system/thread.h>
-#include <util/system/thread.h>
-#include <time.h>
-
-inline void SetCurrentThreadName(const TString& name,
- const ui32 maxCharsFromProcessName = 8) {
-#if defined(_linux_)
- // linux limits threadname by 15 + \0
-
- TStringBuf procName(GetExecPath());
- procName = procName.RNextTok('/');
- procName = procName.SubStr(0, maxCharsFromProcessName);
-
- TStringStream linuxName;
- linuxName << procName << "." << name;
- TThread::SetCurrentThreadName(linuxName.Str().data());
-#else
- Y_UNUSED(maxCharsFromProcessName);
- TThread::SetCurrentThreadName(name.data());
-#endif
-}
diff --git a/library/cpp/actors/util/thread_load_log.h b/library/cpp/actors/util/thread_load_log.h
deleted file mode 100644
index 132e99a52d..0000000000
--- a/library/cpp/actors/util/thread_load_log.h
+++ /dev/null
@@ -1,363 +0,0 @@
-#pragma once
-
-#include "defs.h"
-
-#include <util/system/types.h>
-
-#include <type_traits>
-#include <algorithm>
-#include <atomic>
-#include <limits>
-#include <queue>
-
-template <ui64 TIME_SLOT_COUNT, ui64 TIME_SLOT_LENGTH_NS = 131'072, typename Type = std::uint8_t>
-class TThreadLoad {
-public:
- using TimeSlotType = Type;
-
-private:
- static constexpr auto TIME_SLOT_MAX_VALUE = std::numeric_limits<TimeSlotType>::max();
- static constexpr ui64 TIME_SLOT_PART_COUNT = TIME_SLOT_MAX_VALUE + 1;
- static constexpr auto TIME_SLOT_PART_LENGTH_NS = TIME_SLOT_LENGTH_NS / TIME_SLOT_PART_COUNT;
-
- template <typename T>
- static void AtomicAddBound(std::atomic<T>& val, i64 inc) {
- if (inc == 0) {
- return;
- }
-
- auto newVal = val.load();
- auto oldVal = newVal;
-
- do {
- static constexpr auto MAX_VALUE = std::numeric_limits<T>::max();
-
- if (oldVal >= MAX_VALUE) {
- return;
- }
- newVal = std::min<i64>(MAX_VALUE, static_cast<i64>(oldVal) + inc);
- } while (!val.compare_exchange_weak(oldVal, newVal));
- }
-
- template <typename T>
- static void AtomicSubBound(std::atomic<T>& val, i64 sub) {
- if (sub == 0) {
- return;
- }
-
- auto newVal = val.load();
- auto oldVal = newVal;
-
- do {
- if (oldVal == 0) {
- return;
- }
- newVal = std::max<i64>(0, static_cast<i64>(oldVal) - sub);
- } while (!val.compare_exchange_weak(oldVal, newVal));
- }
-
- void UpdateCompleteTimeSlots(ui64 firstSlotNumber, ui64 lastSlotNumber, TimeSlotType timeSlotValue) {
- ui32 firstSlotIndex = firstSlotNumber % TIME_SLOT_COUNT;
- ui32 lastSlotIndex = lastSlotNumber % TIME_SLOT_COUNT;
-
- const ui64 firstTimeSlotsPass = firstSlotNumber / TIME_SLOT_COUNT;
- const ui64 lastTimeSlotsPass = lastSlotNumber / TIME_SLOT_COUNT;
-
- if (firstTimeSlotsPass == lastTimeSlotsPass) {
- // first and last time slots are in the same pass
- for (auto slotNumber = firstSlotNumber + 1; slotNumber < lastSlotNumber; ++slotNumber) {
- auto slotIndex = slotNumber % TIME_SLOT_COUNT;
- TimeSlots[slotIndex] = timeSlotValue;
- }
- } else if (firstTimeSlotsPass + 1 == lastTimeSlotsPass) {
- for (auto slotIndex = (firstSlotNumber + 1) % TIME_SLOT_COUNT; firstSlotIndex < slotIndex && slotIndex < TIME_SLOT_COUNT; ++slotIndex) {
- TimeSlots[slotIndex] = timeSlotValue;
- }
- for (auto slotIndex = 0u; slotIndex < lastSlotIndex; ++slotIndex) {
- TimeSlots[slotIndex] = timeSlotValue;
- }
- } else {
- for (auto slotIndex = 0u; slotIndex < TIME_SLOT_COUNT; ++slotIndex) {
- TimeSlots[slotIndex] = timeSlotValue;
- }
- }
- }
-
-public:
- std::atomic<ui64> LastTimeNs;
- std::atomic<TimeSlotType> TimeSlots[TIME_SLOT_COUNT];
- std::atomic<bool> LastRegisteredPeriodIsBusy = false;
-
- explicit TThreadLoad(ui64 timeNs = 0) {
- static_assert(std::is_unsigned<TimeSlotType>::value);
-
- LastTimeNs = timeNs;
- for (size_t i = 0; i < TIME_SLOT_COUNT; ++i) {
- TimeSlots[i] = 0;
- }
- }
-
- static constexpr auto GetTimeSlotCount() {
- return TIME_SLOT_COUNT;
- }
-
- static constexpr auto GetTimeSlotLengthNs() {
- return TIME_SLOT_LENGTH_NS;
- }
-
- static constexpr auto GetTimeSlotPartLengthNs() {
- return TIME_SLOT_PART_LENGTH_NS;
- }
-
- static constexpr auto GetTimeSlotPartCount() {
- return TIME_SLOT_PART_COUNT;
- }
-
- static constexpr auto GetTimeSlotMaxValue() {
- return TIME_SLOT_MAX_VALUE;
- }
-
- static constexpr auto GetTimeWindowLengthNs() {
- return TIME_SLOT_COUNT * TIME_SLOT_LENGTH_NS;
- }
-
- void RegisterBusyPeriod(ui64 timeNs) {
- RegisterBusyPeriod<true>(timeNs, LastTimeNs.load());
- }
-
- template <bool ModifyLastTime>
- void RegisterBusyPeriod(ui64 timeNs, ui64 lastTimeNs) {
- LastRegisteredPeriodIsBusy = true;
-
- if (timeNs < lastTimeNs) {
- // when time goes back, mark all time slots as 'free'
- for (size_t i = 0u; i < TIME_SLOT_COUNT; ++i) {
- TimeSlots[i] = 0;
- }
-
- if (ModifyLastTime) {
- LastTimeNs = timeNs;
- }
-
- return;
- }
-
- // lastTimeNs <= timeNs
- ui64 firstSlotNumber = lastTimeNs / TIME_SLOT_LENGTH_NS;
- ui32 firstSlotIndex = firstSlotNumber % TIME_SLOT_COUNT;
- ui64 lastSlotNumber = timeNs / TIME_SLOT_LENGTH_NS;
- ui32 lastSlotIndex = lastSlotNumber % TIME_SLOT_COUNT;
-
- if (firstSlotNumber == lastSlotNumber) {
- ui32 slotLengthNs = timeNs - lastTimeNs;
- ui32 slotPartsCount = (slotLengthNs + TIME_SLOT_PART_LENGTH_NS - 1) / TIME_SLOT_PART_LENGTH_NS;
- AtomicAddBound(TimeSlots[firstSlotIndex], slotPartsCount);
-
- if (ModifyLastTime) {
- LastTimeNs = timeNs;
- }
- return;
- }
-
- ui32 firstSlotLengthNs = TIME_SLOT_LENGTH_NS - (lastTimeNs % TIME_SLOT_LENGTH_NS);
- ui32 firstSlotPartsCount = (firstSlotLengthNs + TIME_SLOT_PART_LENGTH_NS - 1) / TIME_SLOT_PART_LENGTH_NS;
- ui32 lastSlotLengthNs = timeNs % TIME_SLOT_LENGTH_NS;
- ui32 lastSlotPartsCount = (lastSlotLengthNs + TIME_SLOT_PART_LENGTH_NS - 1) / TIME_SLOT_PART_LENGTH_NS;
-
- // process first time slot
- AtomicAddBound(TimeSlots[firstSlotIndex], firstSlotPartsCount);
-
- // process complete time slots
- UpdateCompleteTimeSlots(firstSlotNumber, lastSlotNumber, TIME_SLOT_MAX_VALUE);
-
- // process last time slot
- AtomicAddBound(TimeSlots[lastSlotIndex], lastSlotPartsCount);
-
- if (ModifyLastTime) {
- LastTimeNs = timeNs;
- }
- }
-
- void RegisterIdlePeriod(ui64 timeNs) {
- LastRegisteredPeriodIsBusy = false;
-
- ui64 lastTimeNs = LastTimeNs.load();
- if (timeNs < lastTimeNs) {
- // when time goes back, mark all time slots as 'busy'
- for (size_t i = 0u; i < TIME_SLOT_COUNT; ++i) {
- TimeSlots[i] = TIME_SLOT_MAX_VALUE;
- }
- LastTimeNs = timeNs;
- return;
- }
-
- // lastTimeNs <= timeNs
- ui64 firstSlotNumber = lastTimeNs / TIME_SLOT_LENGTH_NS;
- ui32 firstSlotIndex = firstSlotNumber % TIME_SLOT_COUNT;
- ui64 lastSlotNumber = timeNs / TIME_SLOT_LENGTH_NS;
- ui32 lastSlotIndex = lastSlotNumber % TIME_SLOT_COUNT;
-
- if (firstSlotNumber == lastSlotNumber) {
- ui32 slotLengthNs = timeNs - lastTimeNs;
- ui32 slotPartsCount = slotLengthNs / TIME_SLOT_PART_LENGTH_NS;
-
- AtomicSubBound(TimeSlots[firstSlotIndex], slotPartsCount);
-
- LastTimeNs = timeNs;
- return;
- }
-
- ui32 firstSlotLengthNs = TIME_SLOT_LENGTH_NS - (lastTimeNs % TIME_SLOT_LENGTH_NS);
- ui32 firstSlotPartsCount = (firstSlotLengthNs + TIME_SLOT_PART_LENGTH_NS - 1) / TIME_SLOT_PART_LENGTH_NS;
- ui32 lastSlotLengthNs = timeNs % TIME_SLOT_LENGTH_NS;
- ui32 lastSlotPartsCount = (lastSlotLengthNs + TIME_SLOT_PART_LENGTH_NS - 1) / TIME_SLOT_PART_LENGTH_NS;
-
- // process first time slot
- AtomicSubBound(TimeSlots[firstSlotIndex], firstSlotPartsCount);
-
- // process complete time slots
- UpdateCompleteTimeSlots(firstSlotNumber, lastSlotNumber, 0);
-
- // process last time slot
- AtomicSubBound(TimeSlots[lastSlotIndex], lastSlotPartsCount);
-
- LastTimeNs = timeNs;
- }
-};
-
-class TMinusOneThreadEstimator {
-private:
- template <typename T, int MaxSize>
- class TArrayQueue {
- public:
- bool empty() const {
- return FrontIndex == -1;
- }
-
- bool full() const {
- return (RearIndex + 1) % MaxSize == FrontIndex;
- }
-
- T& front() {
- return Data[FrontIndex];
- }
-
- bool push(T &&t) {
- if (full()) {
- return false;
- }
-
- if (FrontIndex == -1) {
- FrontIndex = 0;
- }
-
- RearIndex = (RearIndex + 1) % MaxSize;
- Data[RearIndex] = std::move(t);
- return true;
- }
-
- bool pop() {
- if (empty()) {
- return false;
- }
-
- if (FrontIndex == RearIndex) {
- FrontIndex = RearIndex = -1;
- } else {
- FrontIndex = (FrontIndex + 1) % MaxSize;
- }
-
- return true;
- }
-
- private:
- int FrontIndex = -1;
- int RearIndex = -1;
- T Data[MaxSize];
- };
-
-public:
- template <typename T>
- ui64 MaxLatencyIncreaseWithOneLessCpu(T **threadLoads, ui32 threadCount, ui64 timeNs, ui64 periodNs) {
- Y_ABORT_UNLESS(threadCount > 0);
-
- struct TTimeSlotData {
- typename T::TimeSlotType Load;
- ui64 Index;
- };
-
- ui64 lastTimeNs = timeNs;
- for (auto threadIndex = 0u; threadIndex < threadCount; ++threadIndex) {
- if (threadLoads[threadIndex]->LastRegisteredPeriodIsBusy.load()) {
- lastTimeNs = std::min(lastTimeNs, threadLoads[threadIndex]->LastTimeNs.load());
- } else {
- // make interval [lastTimeNs, timeNs] 'busy'
- threadLoads[threadIndex]->template RegisterBusyPeriod<false>(timeNs, threadLoads[threadIndex]->LastTimeNs.load());
- }
- }
-
- periodNs = std::min(T::GetTimeWindowLengthNs(), periodNs);
-
- ui64 beginTimeNs = periodNs < timeNs ? timeNs - periodNs : 0;
-
- ui64 firstSlotNumber = beginTimeNs / T::GetTimeSlotLengthNs();
- ui64 lastSlotNumber = (lastTimeNs + T::GetTimeSlotLengthNs() - 1) / T::GetTimeSlotLengthNs();
-
- ui64 maxTimeSlotShiftCount = 0u;
- TArrayQueue<TTimeSlotData, T::GetTimeSlotCount()> firstThreadLoadDataQueue;
-
- for (auto slotNumber = firstSlotNumber; slotNumber < lastSlotNumber; ++slotNumber) {
- ui64 slotIndex = slotNumber % T::GetTimeSlotCount();
-
- typename T::TimeSlotType firstThreadTimeSlotValue = threadLoads[0]->TimeSlots[slotIndex].load();
-
- // distribute previous load of the first thread by other threads
- auto foundIdleThread = false;
-
- for (auto threadIndex = 1u; threadIndex < threadCount; ++threadIndex) {
- typename T::TimeSlotType thisThreadAvailableTimeSlotLoad = threadLoads[threadIndex]->GetTimeSlotMaxValue() - threadLoads[threadIndex]->TimeSlots[slotIndex].load();
-
- while (!firstThreadLoadDataQueue.empty() && thisThreadAvailableTimeSlotLoad > 0) {
- auto& firstThreadLoadData = firstThreadLoadDataQueue.front();
-
- auto distributedLoad = std::min(thisThreadAvailableTimeSlotLoad, firstThreadLoadData.Load);
-
- thisThreadAvailableTimeSlotLoad -= distributedLoad;
- firstThreadLoadData.Load -= distributedLoad;
-
- if (firstThreadLoadData.Load == 0) {
- auto timeSlotShiftCount = slotIndex - firstThreadLoadData.Index;
- maxTimeSlotShiftCount = std::max(maxTimeSlotShiftCount, timeSlotShiftCount);
- auto res = firstThreadLoadDataQueue.pop();
- Y_ABORT_UNLESS(res);
- }
- }
-
- if (thisThreadAvailableTimeSlotLoad == threadLoads[threadIndex]->GetTimeSlotMaxValue()) {
- foundIdleThread = true;
- }
- }
-
- // distribute current load of the first thread by other threads
- if (firstThreadTimeSlotValue > 0) {
- if (foundIdleThread) {
- // The current load of the first thead can be
- // moved to the idle thread so there is nothing to do
- } else {
- // The current load of the first thread can be later
- // processed by the following time slots of other threads
- auto res = firstThreadLoadDataQueue.push({firstThreadTimeSlotValue, slotIndex});
- Y_ABORT_UNLESS(res);
- }
- }
- }
-
- if (!firstThreadLoadDataQueue.empty()) {
- const auto& timeSlotData = firstThreadLoadDataQueue.front();
- auto timeSlotShiftCount = T::GetTimeSlotCount() - timeSlotData.Index;
- maxTimeSlotShiftCount = std::max(maxTimeSlotShiftCount, timeSlotShiftCount);
- }
-
- return maxTimeSlotShiftCount * T::GetTimeSlotLengthNs();
- }
-};
diff --git a/library/cpp/actors/util/thread_load_log_ut.cpp b/library/cpp/actors/util/thread_load_log_ut.cpp
deleted file mode 100644
index 20e776cff6..0000000000
--- a/library/cpp/actors/util/thread_load_log_ut.cpp
+++ /dev/null
@@ -1,966 +0,0 @@
-#include "thread_load_log.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-
-#include <util/random/random.h>
-#include <util/system/hp_timer.h>
-#include <util/system/thread.h>
-#include <util/system/types.h>
-#include <util/system/sanitizers.h>
-
-#include <limits>
-
-Y_UNIT_TEST_SUITE(ThreadLoadLog) {
-
- Y_UNIT_TEST(TThreadLoad8BitSlotType) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using TSlotType = std::uint8_t;
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, TSlotType>;
-
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeWindowLengthNs(), timeWindowLengthNs);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotLengthNs(), timeSlotLengthNs);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotCount(), timeSlotCount);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotMaxValue(), std::numeric_limits<TSlotType>::max());
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotPartCount(), (ui64)std::numeric_limits<TSlotType>::max() + 1);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotPartLengthNs(), T::GetTimeSlotLengthNs() / T::GetTimeSlotPartCount());
- }
-
- Y_UNIT_TEST(TThreadLoad16BitSlotType) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using TSlotType = std::uint16_t;
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, TSlotType>;
-
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeWindowLengthNs(), timeWindowLengthNs);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotLengthNs(), timeSlotLengthNs);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotCount(), timeSlotCount);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotMaxValue(), std::numeric_limits<TSlotType>::max());
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotPartCount(), (ui64)std::numeric_limits<TSlotType>::max() + 1);
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotPartLengthNs(), T::GetTimeSlotLengthNs() / T::GetTimeSlotPartCount());
- }
-
- Y_UNIT_TEST(TThreadLoad8BitSlotTypeWindowBusy) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using TSlotType = std::uint8_t;
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, TSlotType>;
-
- T threadLoad;
- threadLoad.RegisterBusyPeriod(T::GetTimeWindowLengthNs());
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), T::GetTimeWindowLengthNs());
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), T::GetTimeSlotMaxValue());
- }
- }
-
- Y_UNIT_TEST(TThreadLoad16BitSlotTypeWindowBusy) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using TSlotType = std::uint16_t;
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, TSlotType>;
-
- T threadLoad;
- threadLoad.RegisterBusyPeriod(T::GetTimeWindowLengthNs());
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), T::GetTimeWindowLengthNs());
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), T::GetTimeSlotMaxValue());
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTimeSlot1) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTimeSlot2) {
- using T = TThreadLoad<38400>;
-
- ui32 startNs = 2 * T::GetTimeSlotPartLengthNs();
- T threadLoad(startNs);
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 3 * T::GetTimeSlotPartLengthNs() - 1;
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
-
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTimeSlot3) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTimeSlot4) {
- using T = TThreadLoad<38400>;
-
- ui32 startNs = 2 * T::GetTimeSlotPartLengthNs();
- T threadLoad(startNs);
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 3 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), (timeNs - startNs) / T::GetTimeSlotPartLengthNs());
-
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTwoTimeSlots1) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 2 * threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstTwoTimeSlots2) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 2 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstThreeTimeSlots1) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 3 * threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 3u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstThreeTimeSlots2) {
- TThreadLoad<38400> threadLoad;
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
-
- for (auto slotIndex = 3u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterBusyPeriodFirstThreeTimeSlots3) {
- using T = TThreadLoad<38400>;
-
- ui32 startNs = 3 * T::GetTimeSlotPartLengthNs();
- T threadLoad(startNs);
-
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 0;
- threadLoad.RegisterBusyPeriod(timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTimeSlot1) {
- using T = TThreadLoad<38400>;
-
- ui64 timeNs = T::GetTimeSlotPartLengthNs();
- T threadLoad(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 3 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 0);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 4 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTimeSlot2) {
- using T = TThreadLoad<38400>;
-
- ui64 timeNs = T::GetTimeSlotPartLengthNs();
- T threadLoad(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 3 * T::GetTimeSlotPartLengthNs() - 1;
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 4 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 3);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTimeSlot3) {
- using T = TThreadLoad<38400>;
-
- ui64 timeNs = T::GetTimeSlotPartLengthNs();
- T threadLoad(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 3 * T::GetTimeSlotPartLengthNs() - 1;
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 4 * T::GetTimeSlotPartLengthNs() - 2;
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 5 * T::GetTimeSlotPartLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 3);
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTwoTimeSlots1) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTwoTimeSlots2) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstTwoTimeSlots3) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = 2 * threadLoad.GetTimeSlotLengthNs() - 1;
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 1);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstThreeTimeSlots1) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- timeNs = 2 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- timeNs = 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 3u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstThreeTimeSlots2) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- timeNs = 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 1u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstThreeTimeSlots3) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- timeNs = 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 3u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstThreeTimeSlots4) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = threadLoad.GetTimeSlotLengthNs() + 2 * threadLoad.GetTimeSlotPartLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- timeNs = 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotPartCount() - 2);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 3u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodFirstThreeTimeSlots5) {
- using T = TThreadLoad<38400>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 2 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 2u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = timeNs + threadLoad.GetTimeWindowLengthNs() + threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(TThreadLoadRegisterIdlePeriodOverTimeWindow) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint8_t>;
-
- T threadLoad;
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), 0);
- for (auto slotIndex = 0u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- ui64 timeNs = 5 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[3].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[4].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 5u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
-
- timeNs = timeNs + threadLoad.GetTimeWindowLengthNs() - 3 * threadLoad.GetTimeSlotLengthNs();
- threadLoad.RegisterIdlePeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.LastTimeNs.load(), timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[0].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[1].load(), 0);
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[2].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[3].load(), threadLoad.GetTimeSlotMaxValue());
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[4].load(), threadLoad.GetTimeSlotMaxValue());
- for (auto slotIndex = 5u; slotIndex < threadLoad.GetTimeSlotCount(); ++slotIndex) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoad.TimeSlots[slotIndex].load(), 0);
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsZeroShiftNs) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- UNIT_ASSERT_VALUES_EQUAL(T::GetTimeSlotPartCount(), (ui64)std::numeric_limits<std::uint16_t>::max() + 1);
-
- T *threadLoads[2];
- threadLoads[0] = new T;
- threadLoads[1] = new T;
-
- for (ui64 i = 1; i < timeSlotCount; i += 2) {
- threadLoads[0]->RegisterIdlePeriod(i * T::GetTimeSlotLengthNs());
- threadLoads[0]->RegisterBusyPeriod((i + 1) * T::GetTimeSlotLengthNs());
- }
-
- for (ui64 i = 1; i < timeSlotCount; i += 2) {
- threadLoads[1]->RegisterBusyPeriod(i * T::GetTimeSlotLengthNs());
- threadLoads[1]->RegisterIdlePeriod((i + 1) * T::GetTimeSlotLengthNs());
- }
-
- TMinusOneThreadEstimator estimator;
- ui64 value = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, 2, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
- UNIT_ASSERT_VALUES_EQUAL(value, 0);
-
- delete threadLoads[0];
- delete threadLoads[1];
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsOneTimeSlotShift1) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 2;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
-
- for (ui64 i = 2; i < threadLoads[t]->GetTimeSlotCount(); i += 2) {
- threadLoads[t]->RegisterIdlePeriod((i - 1) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterBusyPeriod(i * T::GetTimeSlotLengthNs());
- }
-
- threadLoads[t]->RegisterIdlePeriod((threadLoads[t]->GetTimeSlotCount() - 1) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterBusyPeriod(threadLoads[t]->GetTimeSlotCount() * T::GetTimeSlotLengthNs());
-
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 2 == 1) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- TMinusOneThreadEstimator estimator;
- auto result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
-
- for (ui64 t = 0; t < threadCount; ++t) {
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 2 == 1) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, T::GetTimeSlotLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsOneTimeSlotShift2) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 2;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
-
- for (ui64 i = 2; i < threadLoads[t]->GetTimeSlotCount(); i += 2) {
- threadLoads[t]->RegisterBusyPeriod((i - 1) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterIdlePeriod(i * T::GetTimeSlotLengthNs());
- }
-
- threadLoads[t]->RegisterBusyPeriod((threadLoads[t]->GetTimeSlotCount() - 1) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterIdlePeriod(threadLoads[t]->GetTimeSlotCount() * T::GetTimeSlotLengthNs());
-
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 2 == 0) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- TMinusOneThreadEstimator estimator;
- auto result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
-
- for (ui64 t = 0; t < threadCount; ++t) {
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 2 == 0) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, T::GetTimeSlotLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsTwoTimeSlotsShift1) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 2;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
-
- for (ui64 i = 4; i < threadLoads[t]->GetTimeSlotCount(); i += 4) {
- threadLoads[t]->RegisterIdlePeriod((i - 2) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterBusyPeriod(i * T::GetTimeSlotLengthNs());
- }
-
- threadLoads[t]->RegisterIdlePeriod((threadLoads[t]->GetTimeSlotCount() - 2) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterBusyPeriod(threadLoads[t]->GetTimeSlotCount() * T::GetTimeSlotLengthNs());
-
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 4 == 2 || s % 4 == 3) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- TMinusOneThreadEstimator estimator;
- auto result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
-
- for (ui64 t = 0; t < threadCount; ++t) {
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 4 == 2 || s % 4 == 3) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->TimeSlots[s].load(), 0);
- }
- }
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, 2 * T::GetTimeSlotLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsTwoTimeSlotsShift2) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 2;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
-
- for (ui64 i = 4; i < threadLoads[t]->GetTimeSlotCount(); i += 4) {
- threadLoads[t]->RegisterBusyPeriod((i - 2) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterIdlePeriod(i * T::GetTimeSlotLengthNs());
- }
-
- threadLoads[t]->RegisterBusyPeriod((threadLoads[t]->GetTimeSlotCount() - 2) * T::GetTimeSlotLengthNs());
- threadLoads[t]->RegisterIdlePeriod(threadLoads[t]->GetTimeSlotCount() * T::GetTimeSlotLengthNs());
-
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 4 == 0 || s % 4 == 1) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- TMinusOneThreadEstimator estimator;
- auto result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
-
- for (ui64 t = 0; t < threadCount; ++t) {
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- if (s % 4 == 0 || s % 4 == 1) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- } else {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
- }
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, 2 * T::GetTimeSlotLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimatorTwoThreadLoadsTwoTimeSlotsShift3) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 2;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
-
- auto timeNs = T::GetTimeWindowLengthNs() - 1.5 * T::GetTimeSlotLengthNs();
- threadLoads[t]->RegisterIdlePeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->LastTimeNs.load(), timeNs);
-
- timeNs = T::GetTimeWindowLengthNs();
- threadLoads[t]->RegisterBusyPeriod(timeNs);
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->LastTimeNs.load(), timeNs);
-
- for (ui64 s = 0; s + 2 < threadLoads[t]->GetTimeSlotCount(); ++s) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->TimeSlots[timeSlotCount - 2].load(), T::GetTimeSlotPartCount() / 2);
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->TimeSlots[timeSlotCount - 1].load(), T::GetTimeSlotMaxValue());
- }
-
- TMinusOneThreadEstimator estimator;
- auto result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- for (ui64 s = 0; s + 2 < threadLoads[t]->GetTimeSlotCount(); ++s) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), 0, ToString(s).c_str());
- }
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->TimeSlots[timeSlotCount - 2].load(), T::GetTimeSlotPartCount() / 2);
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->TimeSlots[timeSlotCount - 1].load(), T::GetTimeSlotMaxValue());
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, 2 * T::GetTimeSlotLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
-
- Y_UNIT_TEST(MinusOneThreadEstimator16ThreadLoadsAllTimeSlots) {
- constexpr auto timeWindowLengthNs = 5368709120ull; // 5 * 2 ^ 30 ~5 sec
- constexpr auto timeSlotLengthNs = 524288ull; // 2 ^ 19 ns ~ 512 usec
- constexpr auto timeSlotCount = timeWindowLengthNs / timeSlotLengthNs;
- constexpr auto threadCount = 16;
- constexpr auto estimatesCount = 16;
-
- using T = TThreadLoad<timeSlotCount, timeSlotLengthNs, std::uint16_t>;
-
- for (auto e = 0u; e < estimatesCount; ++e) {
- T *threadLoads[threadCount];
-
- for (auto t = 0u; t < threadCount; ++t) {
- threadLoads[t] = new T;
- auto timeNs = threadLoads[t]->GetTimeWindowLengthNs();
- threadLoads[t]->RegisterBusyPeriod(timeNs);
-
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->LastTimeNs.load(), timeNs);
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- }
- }
-
- ui64 result = 0;
- {
- THPTimer timer;
- TMinusOneThreadEstimator estimator;
- result = estimator.MaxLatencyIncreaseWithOneLessCpu(threadLoads, threadCount, T::GetTimeWindowLengthNs(), T::GetTimeWindowLengthNs());
- // output in microseconds
- auto passed = timer.Passed() * 1000000;
- Y_UNUSED(passed);
- // Cerr << "timer : " << passed << " " << __LINE__ << Endl;
- }
-
- for (ui64 t = 0; t < threadCount; ++t) {
- UNIT_ASSERT_VALUES_EQUAL(threadLoads[t]->LastTimeNs.load(), T::GetTimeWindowLengthNs());
- for (ui64 s = 0; s < threadLoads[t]->GetTimeSlotCount(); ++s) {
- UNIT_ASSERT_VALUES_EQUAL_C(threadLoads[t]->TimeSlots[s].load(), T::GetTimeSlotMaxValue(), ToString(s).c_str());
- }
- }
-
- UNIT_ASSERT_VALUES_EQUAL(result, T::GetTimeWindowLengthNs());
-
- for (auto t = 0u; t < threadCount; ++t) {
- delete threadLoads[t];
- }
- }
- }
-}
diff --git a/library/cpp/actors/util/threadparkpad.cpp b/library/cpp/actors/util/threadparkpad.cpp
deleted file mode 100644
index b939d6b61a..0000000000
--- a/library/cpp/actors/util/threadparkpad.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "threadparkpad.h"
-#include <util/system/winint.h>
-
-#ifdef _linux_
-
-#include "futex.h"
-
-namespace NActors {
- class TThreadParkPad::TImpl {
- volatile bool Interrupted;
- int Futex;
-
- public:
- TImpl()
- : Interrupted(false)
- , Futex(0)
- {
- }
- ~TImpl() {
- }
-
- bool Park() noexcept {
- __atomic_fetch_sub(&Futex, 1, __ATOMIC_SEQ_CST);
- while (__atomic_load_n(&Futex, __ATOMIC_ACQUIRE) == -1)
- SysFutex(&Futex, FUTEX_WAIT_PRIVATE, -1, nullptr, nullptr, 0);
- return IsInterrupted();
- }
-
- void Unpark() noexcept {
- const int old = __atomic_fetch_add(&Futex, 1, __ATOMIC_SEQ_CST);
- if (old == -1)
- SysFutex(&Futex, FUTEX_WAKE_PRIVATE, -1, nullptr, nullptr, 0);
- }
-
- void Interrupt() noexcept {
- __atomic_store_n(&Interrupted, true, __ATOMIC_SEQ_CST);
- Unpark();
- }
-
- bool IsInterrupted() const noexcept {
- return __atomic_load_n(&Interrupted, __ATOMIC_ACQUIRE);
- }
- };
-
-#elif defined _win32_
-#include <library/cpp/deprecated/atomic/atomic.h>
-
-#include <util/generic/bt_exception.h>
-#include <util/generic/yexception.h>
-
-namespace NActors {
- class TThreadParkPad::TImpl {
- TAtomic Interrupted;
- HANDLE EvHandle;
-
- public:
- TImpl()
- : Interrupted(false)
- {
- EvHandle = ::CreateEvent(0, false, false, 0);
- if (!EvHandle)
- ythrow TWithBackTrace<yexception>() << "::CreateEvent failed";
- }
- ~TImpl() {
- if (EvHandle)
- ::CloseHandle(EvHandle);
- }
-
- bool Park() noexcept {
- ::WaitForSingleObject(EvHandle, INFINITE);
- return AtomicGet(Interrupted);
- }
-
- void Unpark() noexcept {
- ::SetEvent(EvHandle);
- }
-
- void Interrupt() noexcept {
- AtomicSet(Interrupted, true);
- Unpark();
- }
-
- bool IsInterrupted() const noexcept {
- return AtomicGet(Interrupted);
- }
- };
-
-#else
-
-#include <library/cpp/deprecated/atomic/atomic.h>
-
-#include <util/system/event.h>
-
-namespace NActors {
- class TThreadParkPad::TImpl {
- TAtomic Interrupted;
- TSystemEvent Ev;
-
- public:
- TImpl()
- : Interrupted(false)
- , Ev(TSystemEvent::rAuto)
- {
- }
- ~TImpl() {
- }
-
- bool Park() noexcept {
- Ev.Wait();
- return AtomicGet(Interrupted);
- }
-
- void Unpark() noexcept {
- Ev.Signal();
- }
-
- void Interrupt() noexcept {
- AtomicSet(Interrupted, true);
- Unpark();
- }
-
- bool IsInterrupted() const noexcept {
- return AtomicGet(Interrupted);
- }
- };
-#endif
-
- TThreadParkPad::TThreadParkPad()
- : Impl(new TThreadParkPad::TImpl())
- {
- }
-
- TThreadParkPad::~TThreadParkPad() {
- }
-
- bool TThreadParkPad::Park() noexcept {
- return Impl->Park();
- }
-
- void TThreadParkPad::Unpark() noexcept {
- Impl->Unpark();
- }
-
- void TThreadParkPad::Interrupt() noexcept {
- Impl->Interrupt();
- }
-
- bool TThreadParkPad::Interrupted() const noexcept {
- return Impl->IsInterrupted();
- }
-
-}
diff --git a/library/cpp/actors/util/threadparkpad.h b/library/cpp/actors/util/threadparkpad.h
deleted file mode 100644
index 5b574ccf34..0000000000
--- a/library/cpp/actors/util/threadparkpad.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <util/generic/ptr.h>
-
-namespace NActors {
- class TThreadParkPad {
- private:
- class TImpl;
- THolder<TImpl> Impl;
-
- public:
- TThreadParkPad();
- ~TThreadParkPad();
-
- bool Park() noexcept;
- void Unpark() noexcept;
- void Interrupt() noexcept;
- bool Interrupted() const noexcept;
- };
-
-}
diff --git a/library/cpp/actors/util/ticket_lock.h b/library/cpp/actors/util/ticket_lock.h
deleted file mode 100644
index 30355c3390..0000000000
--- a/library/cpp/actors/util/ticket_lock.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-#include "intrinsics.h"
-#include <util/system/guard.h>
-#include <util/system/yassert.h>
-
-class TTicketLock : TNonCopyable {
- ui32 TicketIn;
- ui32 TicketOut;
-
-public:
- TTicketLock()
- : TicketIn(0)
- , TicketOut(0)
- {
- }
-
- void Release() noexcept {
- AtomicUi32Increment(&TicketOut);
- }
-
- ui32 Acquire() noexcept {
- ui32 revolves = 0;
- const ui32 ticket = AtomicUi32Increment(&TicketIn) - 1;
- while (ticket != AtomicLoad(&TicketOut)) {
- Y_DEBUG_ABORT_UNLESS(ticket >= AtomicLoad(&TicketOut));
- SpinLockPause();
- ++revolves;
- }
- return revolves;
- }
-
- bool TryAcquire() noexcept {
- const ui32 x = AtomicLoad(&TicketOut);
- if (x == AtomicLoad(&TicketIn) && AtomicUi32Cas(&TicketIn, x + 1, x))
- return true;
- else
- return false;
- }
-
- bool IsLocked() noexcept {
- const ui32 ticketIn = AtomicLoad(&TicketIn);
- const ui32 ticketOut = AtomicLoad(&TicketOut);
- return (ticketIn != ticketOut);
- }
-
- typedef ::TGuard<TTicketLock> TGuard;
-};
diff --git a/library/cpp/actors/util/timerfd.h b/library/cpp/actors/util/timerfd.h
deleted file mode 100644
index 78ae27e2ee..0000000000
--- a/library/cpp/actors/util/timerfd.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-#include "datetime.h"
-
-#include <util/generic/noncopyable.h>
-
-#ifdef _linux_
-
-#include <util/system/yassert.h>
-#include <errno.h>
-#include <sys/timerfd.h>
-
-struct TTimerFd: public TNonCopyable {
- int Fd;
-
- TTimerFd() {
- Fd = timerfd_create(CLOCK_MONOTONIC, 0);
- Y_ABORT_UNLESS(Fd != -1, "timerfd_create(CLOCK_MONOTONIC, 0) -> -1; errno:%d: %s", int(errno), strerror(errno));
- }
-
- ~TTimerFd() {
- close(Fd);
- }
-
- void Set(ui64 ts) {
- ui64 now = GetCycleCountFast();
- Arm(now >= ts? 1: NHPTimer::GetSeconds(ts - now) * 1e9);
- }
-
- void Reset() {
- Arm(0); // disarm timer
- }
-
- void Wait() {
- ui64 expirations;
- ssize_t s = read(Fd, &expirations, sizeof(ui64));
- Y_UNUSED(s); // Y_ABORT_UNLESS(s == sizeof(ui64));
- }
-
- void Wake() {
- Arm(1);
- }
-private:
- void Arm(ui64 ns) {
- struct itimerspec spec;
- spec.it_value.tv_sec = ns / 1'000'000'000;
- spec.it_value.tv_nsec = ns % 1'000'000'000;
- spec.it_interval.tv_sec = 0;
- spec.it_interval.tv_nsec = 0;
- int ret = timerfd_settime(Fd, 0, &spec, nullptr);
- Y_ABORT_UNLESS(ret != -1, "timerfd_settime(%d, 0, %" PRIu64 "ns, 0) -> %d; errno:%d: %s", Fd, ns, ret, int(errno), strerror(errno));
- }
-};
-
-#else
-
-struct TTimerFd: public TNonCopyable {
- int Fd = 0;
- void Set(ui64) {}
- void Reset() {}
- void Wait() {}
- void Wake() {}
-};
-
-#endif
diff --git a/library/cpp/actors/util/unordered_cache.h b/library/cpp/actors/util/unordered_cache.h
deleted file mode 100644
index 40794fc04b..0000000000
--- a/library/cpp/actors/util/unordered_cache.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#pragma once
-
-#include "defs.h"
-#include "queue_chunk.h"
-
-template <typename T, ui32 Size = 512, ui32 ConcurrencyFactor = 1, typename TChunk = TQueueChunk<T, Size>>
-class TUnorderedCache : TNonCopyable {
- static_assert(std::is_integral<T>::value || std::is_pointer<T>::value, "expect std::is_integral<T>::value || std::is_pointer<T>::value");
-
-public:
- static constexpr ui32 Concurrency = ConcurrencyFactor * 4;
-
-private:
- struct TReadSlot {
- TChunk* volatile ReadFrom;
- volatile ui32 ReadPosition;
- char Padding[64 - sizeof(TChunk*) - sizeof(ui32)]; // 1 slot per cache line
- };
-
- struct TWriteSlot {
- TChunk* volatile WriteTo;
- volatile ui32 WritePosition;
- char Padding[64 - sizeof(TChunk*) - sizeof(ui32)]; // 1 slot per cache line
- };
-
- static_assert(sizeof(TReadSlot) == 64, "expect sizeof(TReadSlot) == 64");
- static_assert(sizeof(TWriteSlot) == 64, "expect sizeof(TWriteSlot) == 64");
-
-private:
- TReadSlot ReadSlots[Concurrency];
- TWriteSlot WriteSlots[Concurrency];
-
- static_assert(sizeof(TChunk*) == sizeof(TAtomic), "expect sizeof(TChunk*) == sizeof(TAtomic)");
-
-private:
- struct TLockedWriter {
- TWriteSlot* Slot;
- TChunk* WriteTo;
-
- TLockedWriter()
- : Slot(nullptr)
- , WriteTo(nullptr)
- { }
-
- TLockedWriter(TWriteSlot* slot, TChunk* writeTo)
- : Slot(slot)
- , WriteTo(writeTo)
- { }
-
- ~TLockedWriter() noexcept {
- Drop();
- }
-
- void Drop() {
- if (Slot) {
- AtomicStore(&Slot->WriteTo, WriteTo);
- Slot = nullptr;
- }
- }
-
- TLockedWriter(const TLockedWriter&) = delete;
- TLockedWriter& operator=(const TLockedWriter&) = delete;
-
- TLockedWriter(TLockedWriter&& rhs)
- : Slot(rhs.Slot)
- , WriteTo(rhs.WriteTo)
- {
- rhs.Slot = nullptr;
- }
-
- TLockedWriter& operator=(TLockedWriter&& rhs) {
- if (Y_LIKELY(this != &rhs)) {
- Drop();
- Slot = rhs.Slot;
- WriteTo = rhs.WriteTo;
- rhs.Slot = nullptr;
- }
- return *this;
- }
- };
-
-private:
- TLockedWriter LockWriter(ui64 writerRotation) {
- ui32 cycle = 0;
- for (;;) {
- TWriteSlot* slot = &WriteSlots[writerRotation % Concurrency];
- if (AtomicLoad(&slot->WriteTo) != nullptr) {
- if (TChunk* writeTo = AtomicSwap(&slot->WriteTo, nullptr)) {
- return TLockedWriter(slot, writeTo);
- }
- }
- ++writerRotation;
-
- // Do a spinlock pause after a full cycle
- if (++cycle == Concurrency) {
- SpinLockPause();
- cycle = 0;
- }
- }
- }
-
- void WriteOne(TLockedWriter& lock, T x) {
- Y_DEBUG_ABORT_UNLESS(x != 0);
-
- const ui32 pos = AtomicLoad(&lock.Slot->WritePosition);
- if (pos != TChunk::EntriesCount) {
- AtomicStore(&lock.Slot->WritePosition, pos + 1);
- AtomicStore(&lock.WriteTo->Entries[pos], x);
- } else {
- TChunk* next = new TChunk();
- AtomicStore(&next->Entries[0], x);
- AtomicStore(&lock.Slot->WritePosition, 1u);
- AtomicStore(&lock.WriteTo->Next, next);
- lock.WriteTo = next;
- }
- }
-
-public:
- TUnorderedCache() {
- for (ui32 i = 0; i < Concurrency; ++i) {
- ReadSlots[i].ReadFrom = new TChunk();
- ReadSlots[i].ReadPosition = 0;
-
- WriteSlots[i].WriteTo = ReadSlots[i].ReadFrom;
- WriteSlots[i].WritePosition = 0;
- }
- }
-
- ~TUnorderedCache() {
- Y_ABORT_UNLESS(!Pop(0));
-
- for (ui64 i = 0; i < Concurrency; ++i) {
- if (ReadSlots[i].ReadFrom) {
- delete ReadSlots[i].ReadFrom;
- ReadSlots[i].ReadFrom = nullptr;
- }
- WriteSlots[i].WriteTo = nullptr;
- }
- }
-
- T Pop(ui64 readerRotation) noexcept {
- ui64 readerIndex = readerRotation;
- const ui64 endIndex = readerIndex + Concurrency;
- for (; readerIndex != endIndex; ++readerIndex) {
- TReadSlot* slot = &ReadSlots[readerIndex % Concurrency];
- if (AtomicLoad(&slot->ReadFrom) != nullptr) {
- if (TChunk* readFrom = AtomicSwap(&slot->ReadFrom, nullptr)) {
- const ui32 pos = AtomicLoad(&slot->ReadPosition);
- if (pos != TChunk::EntriesCount) {
- if (T ret = AtomicLoad(&readFrom->Entries[pos])) {
- AtomicStore(&slot->ReadPosition, pos + 1);
- AtomicStore(&slot->ReadFrom, readFrom); // release lock with same chunk
- return ret; // found, return
- } else {
- AtomicStore(&slot->ReadFrom, readFrom); // release lock with same chunk
- }
- } else if (TChunk* next = AtomicLoad(&readFrom->Next)) {
- if (T ret = AtomicLoad(&next->Entries[0])) {
- AtomicStore(&slot->ReadPosition, 1u);
- AtomicStore(&slot->ReadFrom, next); // release lock with next chunk
- delete readFrom;
- return ret;
- } else {
- AtomicStore(&slot->ReadPosition, 0u);
- AtomicStore(&slot->ReadFrom, next); // release lock with new chunk
- delete readFrom;
- }
- } else {
- // nothing in old chunk and no next chunk, just release lock with old chunk
- AtomicStore(&slot->ReadFrom, readFrom);
- }
- }
- }
- }
-
- return 0; // got nothing after full cycle, return
- }
-
- void Push(T x, ui64 writerRotation) {
- TLockedWriter lock = LockWriter(writerRotation);
- WriteOne(lock, x);
- }
-
- void PushBulk(T* x, ui32 xcount, ui64 writerRotation) {
- for (;;) {
- // Fill no more then one queue chunk per round
- const ui32 xround = Min(xcount, (ui32)TChunk::EntriesCount);
-
- {
- TLockedWriter lock = LockWriter(writerRotation++);
- for (T* end = x + xround; x != end; ++x)
- WriteOne(lock, *x);
- }
-
- if (xcount <= TChunk::EntriesCount)
- break;
-
- xcount -= TChunk::EntriesCount;
- }
- }
-};
diff --git a/library/cpp/actors/util/unordered_cache_ut.cpp b/library/cpp/actors/util/unordered_cache_ut.cpp
deleted file mode 100644
index 37865f2f91..0000000000
--- a/library/cpp/actors/util/unordered_cache_ut.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#include "unordered_cache.h"
-
-#include <library/cpp/testing/unittest/registar.h>
-#include <util/random/random.h>
-#include <util/system/hp_timer.h>
-#include <util/system/sanitizers.h>
-#include <util/system/thread.h>
-
-Y_UNIT_TEST_SUITE(UnorderedCache) {
-
- void DoOnePushOnePop(ui64 count) {
- TUnorderedCache<ui64> queue;
-
- ui64 readRotation = 0;
- ui64 writeRotation = 0;
-
- auto popped = queue.Pop(readRotation++);
- UNIT_ASSERT_VALUES_EQUAL(popped, 0u);
-
- for (ui64 i = 0; i < count; ++i) {
- queue.Push(i + 1, writeRotation++);
- popped = queue.Pop(readRotation++);
- UNIT_ASSERT_VALUES_EQUAL(popped, i + 1);
-
- popped = queue.Pop(readRotation++);
- UNIT_ASSERT_VALUES_EQUAL(popped, 0u);
- }
- }
-
- Y_UNIT_TEST(OnePushOnePop) {
- DoOnePushOnePop(1);
- }
-
- Y_UNIT_TEST(OnePushOnePop_Repeat1M) {
- DoOnePushOnePop(1000000);
- }
-
- /**
- * Simplified thread spawning for testing
- */
- class TWorkerThread : public ISimpleThread {
- private:
- std::function<void()> Func;
- double Time = 0.0;
-
- public:
- TWorkerThread(std::function<void()> func)
- : Func(std::move(func))
- { }
-
- double GetTime() const {
- return Time;
- }
-
- static THolder<TWorkerThread> Spawn(std::function<void()> func) {
- THolder<TWorkerThread> thread = MakeHolder<TWorkerThread>(std::move(func));
- thread->Start();
- return thread;
- }
-
- private:
- void* ThreadProc() noexcept override {
- THPTimer timer;
- Func();
- Time = timer.Passed();
- return nullptr;
- }
- };
-
- void DoConcurrentPushPop(size_t threads, ui64 perThreadCount) {
- // Concurrency factor 4 is up to 16 threads
- TUnorderedCache<ui64, 512, 4> queue;
-
- auto workerFunc = [&](size_t threadIndex) {
- ui64 readRotation = 0;
- ui64 writeRotation = 0;
- ui64 readsDone = 0;
- ui64 writesDone = 0;
- for (;;) {
- bool canRead = readsDone < writesDone;
- bool canWrite = writesDone < perThreadCount;
- if (!canRead && !canWrite) {
- break;
- }
- if (canRead && canWrite) {
- // Randomly choose between read and write
- if (RandomNumber<ui64>(2)) {
- canRead = false;
- } else {
- canWrite = false;
- }
- }
- if (canRead) {
- ui64 popped = queue.Pop(readRotation++);
- if (popped) {
- ++readsDone;
- }
- }
- if (canWrite) {
- queue.Push(1 + writesDone * threads + threadIndex, writeRotation++);
- ++writesDone;
- }
- }
- };
-
- TVector<THolder<TWorkerThread>> workers(threads);
- for (size_t i = 0; i < threads; ++i) {
- workers[i] = TWorkerThread::Spawn([workerFunc, i]() {
- workerFunc(i);
- });
- }
-
- double maxTime = 0;
- for (size_t i = 0; i < threads; ++i) {
- workers[i]->Join();
- maxTime = Max(maxTime, workers[i]->GetTime());
- }
-
- auto popped = queue.Pop(0);
- UNIT_ASSERT_VALUES_EQUAL(popped, 0u);
-
- Cerr << "Concurrent with " << threads << " threads: " << maxTime << " seconds" << Endl;
- }
-
- void DoConcurrentPushPop_3times(size_t threads, ui64 perThreadCount) {
- for (size_t i = 0; i < 3; ++i) {
- DoConcurrentPushPop(threads, perThreadCount);
- }
- }
-
- static constexpr ui64 PER_THREAD_COUNT = NSan::PlainOrUnderSanitizer(1000000, 100000);
-
- Y_UNIT_TEST(ConcurrentPushPop_1thread) { DoConcurrentPushPop_3times(1, PER_THREAD_COUNT); }
- Y_UNIT_TEST(ConcurrentPushPop_2threads) { DoConcurrentPushPop_3times(2, PER_THREAD_COUNT); }
- Y_UNIT_TEST(ConcurrentPushPop_4threads) { DoConcurrentPushPop_3times(4, PER_THREAD_COUNT); }
- Y_UNIT_TEST(ConcurrentPushPop_8threads) { DoConcurrentPushPop_3times(8, PER_THREAD_COUNT); }
- Y_UNIT_TEST(ConcurrentPushPop_16threads) { DoConcurrentPushPop_3times(16, PER_THREAD_COUNT); }
-}
diff --git a/library/cpp/actors/util/ut/CMakeLists.darwin-arm64.txt b/library/cpp/actors/util/ut/CMakeLists.darwin-arm64.txt
deleted file mode 100644
index 9b02cd1836..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.darwin-arm64.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-
-add_executable(library-cpp-actors-util-ut)
-target_include_directories(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util
-)
-target_link_libraries(library-cpp-actors-util-ut PUBLIC
- contrib-libs-cxxsupp
- yutil
- cpp-testing-unittest_main
- cpp-actors-util
-)
-target_link_options(library-cpp-actors-util-ut PRIVATE
- -Wl,-platform_version,macos,11.0,11.0
- -fPIC
- -fPIC
- -framework
- CoreFoundation
-)
-target_sources(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/cpu_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/thread_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rope_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/unordered_cache_ut.cpp
-)
-set_property(
- TARGET
- library-cpp-actors-util-ut
- PROPERTY
- SPLIT_FACTOR
- 1
-)
-add_yunittest(
- NAME
- library-cpp-actors-util-ut
- TEST_TARGET
- library-cpp-actors-util-ut
- TEST_ARG
- --print-before-suite
- --print-before-test
- --fork-tests
- --print-times
- --show-fails
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- LABELS
- SMALL
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- PROCESSORS
- 1
-)
-target_allocator(library-cpp-actors-util-ut
- system_allocator
-)
-vcs_info(library-cpp-actors-util-ut)
diff --git a/library/cpp/actors/util/ut/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/util/ut/CMakeLists.darwin-x86_64.txt
deleted file mode 100644
index f02b2d926c..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.darwin-x86_64.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-
-add_executable(library-cpp-actors-util-ut)
-target_include_directories(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util
-)
-target_link_libraries(library-cpp-actors-util-ut PUBLIC
- contrib-libs-cxxsupp
- yutil
- library-cpp-cpuid_check
- cpp-testing-unittest_main
- cpp-actors-util
-)
-target_link_options(library-cpp-actors-util-ut PRIVATE
- -Wl,-platform_version,macos,11.0,11.0
- -fPIC
- -fPIC
- -framework
- CoreFoundation
-)
-target_sources(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/cpu_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/thread_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rope_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/unordered_cache_ut.cpp
-)
-set_property(
- TARGET
- library-cpp-actors-util-ut
- PROPERTY
- SPLIT_FACTOR
- 1
-)
-add_yunittest(
- NAME
- library-cpp-actors-util-ut
- TEST_TARGET
- library-cpp-actors-util-ut
- TEST_ARG
- --print-before-suite
- --print-before-test
- --fork-tests
- --print-times
- --show-fails
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- LABELS
- SMALL
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- PROCESSORS
- 1
-)
-target_allocator(library-cpp-actors-util-ut
- system_allocator
-)
-vcs_info(library-cpp-actors-util-ut)
diff --git a/library/cpp/actors/util/ut/CMakeLists.linux-aarch64.txt b/library/cpp/actors/util/ut/CMakeLists.linux-aarch64.txt
deleted file mode 100644
index 27ff864fef..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.linux-aarch64.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-
-add_executable(library-cpp-actors-util-ut)
-target_include_directories(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util
-)
-target_link_libraries(library-cpp-actors-util-ut PUBLIC
- contrib-libs-linux-headers
- contrib-libs-cxxsupp
- yutil
- cpp-testing-unittest_main
- cpp-actors-util
-)
-target_link_options(library-cpp-actors-util-ut PRIVATE
- -ldl
- -lrt
- -Wl,--no-as-needed
- -fPIC
- -fPIC
- -lpthread
- -lrt
- -ldl
-)
-target_sources(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/cpu_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/thread_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rope_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/unordered_cache_ut.cpp
-)
-set_property(
- TARGET
- library-cpp-actors-util-ut
- PROPERTY
- SPLIT_FACTOR
- 1
-)
-add_yunittest(
- NAME
- library-cpp-actors-util-ut
- TEST_TARGET
- library-cpp-actors-util-ut
- TEST_ARG
- --print-before-suite
- --print-before-test
- --fork-tests
- --print-times
- --show-fails
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- LABELS
- SMALL
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- PROCESSORS
- 1
-)
-target_allocator(library-cpp-actors-util-ut
- cpp-malloc-jemalloc
-)
-vcs_info(library-cpp-actors-util-ut)
diff --git a/library/cpp/actors/util/ut/CMakeLists.linux-x86_64.txt b/library/cpp/actors/util/ut/CMakeLists.linux-x86_64.txt
deleted file mode 100644
index d1143a475b..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.linux-x86_64.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-
-add_executable(library-cpp-actors-util-ut)
-target_include_directories(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util
-)
-target_link_libraries(library-cpp-actors-util-ut PUBLIC
- contrib-libs-linux-headers
- contrib-libs-cxxsupp
- yutil
- library-cpp-cpuid_check
- cpp-testing-unittest_main
- cpp-actors-util
-)
-target_link_options(library-cpp-actors-util-ut PRIVATE
- -ldl
- -lrt
- -Wl,--no-as-needed
- -fPIC
- -fPIC
- -lpthread
- -lrt
- -ldl
-)
-target_sources(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/cpu_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/thread_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rope_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/unordered_cache_ut.cpp
-)
-set_property(
- TARGET
- library-cpp-actors-util-ut
- PROPERTY
- SPLIT_FACTOR
- 1
-)
-add_yunittest(
- NAME
- library-cpp-actors-util-ut
- TEST_TARGET
- library-cpp-actors-util-ut
- TEST_ARG
- --print-before-suite
- --print-before-test
- --fork-tests
- --print-times
- --show-fails
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- LABELS
- SMALL
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- PROCESSORS
- 1
-)
-target_allocator(library-cpp-actors-util-ut
- cpp-malloc-tcmalloc
- libs-tcmalloc-no_percpu_cache
-)
-vcs_info(library-cpp-actors-util-ut)
diff --git a/library/cpp/actors/util/ut/CMakeLists.txt b/library/cpp/actors/util/ut/CMakeLists.txt
deleted file mode 100644
index 2dce3a77fe..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
- include(CMakeLists.linux-aarch64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
- include(CMakeLists.darwin-x86_64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
- include(CMakeLists.darwin-arm64.txt)
-elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
- include(CMakeLists.windows-x86_64.txt)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
- include(CMakeLists.linux-x86_64.txt)
-endif()
diff --git a/library/cpp/actors/util/ut/CMakeLists.windows-x86_64.txt b/library/cpp/actors/util/ut/CMakeLists.windows-x86_64.txt
deleted file mode 100644
index 3af5d98ef0..0000000000
--- a/library/cpp/actors/util/ut/CMakeLists.windows-x86_64.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-
-# This file was generated by the build system used internally in the Yandex monorepo.
-# Only simple modifications are allowed (adding source-files to targets, adding simple properties
-# like target_include_directories). These modifications will be ported to original
-# ya.make files by maintainers. Any complex modifications which can't be ported back to the
-# original buildsystem will not be accepted.
-
-
-
-add_executable(library-cpp-actors-util-ut)
-target_include_directories(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util
-)
-target_link_libraries(library-cpp-actors-util-ut PUBLIC
- contrib-libs-cxxsupp
- yutil
- library-cpp-cpuid_check
- cpp-testing-unittest_main
- cpp-actors-util
-)
-target_sources(library-cpp-actors-util-ut PRIVATE
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/cpu_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/thread_load_log_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rope_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/rc_buf_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
- ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/unordered_cache_ut.cpp
-)
-set_property(
- TARGET
- library-cpp-actors-util-ut
- PROPERTY
- SPLIT_FACTOR
- 1
-)
-add_yunittest(
- NAME
- library-cpp-actors-util-ut
- TEST_TARGET
- library-cpp-actors-util-ut
- TEST_ARG
- --print-before-suite
- --print-before-test
- --fork-tests
- --print-times
- --show-fails
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- LABELS
- SMALL
-)
-set_yunittest_property(
- TEST
- library-cpp-actors-util-ut
- PROPERTY
- PROCESSORS
- 1
-)
-target_allocator(library-cpp-actors-util-ut
- system_allocator
-)
-vcs_info(library-cpp-actors-util-ut)
diff --git a/library/cpp/actors/util/ut/ya.make b/library/cpp/actors/util/ut/ya.make
deleted file mode 100644
index 9ac8504751..0000000000
--- a/library/cpp/actors/util/ut/ya.make
+++ /dev/null
@@ -1,20 +0,0 @@
-UNITTEST_FOR(library/cpp/actors/util)
-
-IF (WITH_VALGRIND)
- TIMEOUT(600)
- SIZE(MEDIUM)
-ENDIF()
-
-SRCS(
- cpu_load_log_ut.cpp
- memory_tracker_ut.cpp
- thread_load_log_ut.cpp
- rope_ut.cpp
- rc_buf_ut.cpp
- shared_data_ut.cpp
- shared_data_rope_backend_ut.cpp
- shared_data_native_rope_backend_ut.cpp
- unordered_cache_ut.cpp
-)
-
-END()
diff --git a/library/cpp/actors/util/ut_helpers.h b/library/cpp/actors/util/ut_helpers.h
deleted file mode 100644
index d3fe873233..0000000000
--- a/library/cpp/actors/util/ut_helpers.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-// calls TCallback for all args permutations including (id, id)
-template <class TCallback, class... TArgs>
-void Permutate(TCallback&& fn, TArgs&&... args)
-{
- auto forAll = [&](auto& arg){
- (fn(std::forward<decltype(arg)>(arg), std::forward<decltype(args)>(args)), ...);
- };
-
- (forAll(std::forward<decltype(args)>(args)), ...);
-}
diff --git a/library/cpp/actors/util/ya.make b/library/cpp/actors/util/ya.make
deleted file mode 100644
index 48d595c156..0000000000
--- a/library/cpp/actors/util/ya.make
+++ /dev/null
@@ -1,50 +0,0 @@
-LIBRARY()
-
-SRCS(
- affinity.cpp
- affinity.h
- cpu_load_log.h
- cpumask.h
- datetime.h
- defs.h
- funnel_queue.h
- futex.h
- intrinsics.h
- local_process_key.h
- named_tuple.h
- queue_chunk.h
- queue_oneone_inplace.h
- memory_track.cpp
- memory_track.h
- memory_tracker.cpp
- memory_tracker.h
- recentwnd.h
- rope.cpp
- rope.h
- rc_buf.cpp
- rc_buf.h
- shared_data.h
- shared_data.cpp
- shared_data_rope_backend.h
- should_continue.cpp
- should_continue.h
- thread.h
- threadparkpad.cpp
- threadparkpad.h
- thread_load_log.h
- ticket_lock.h
- timerfd.h
- unordered_cache.h
-)
-
-PEERDIR(
- library/cpp/containers/absl_flat_hash
- library/cpp/deprecated/atomic
- library/cpp/pop_count
-)
-
-END()
-
-RECURSE_FOR_TESTS(
- ut
-)