diff options
author | vskipin <vskipin@yandex-team.ru> | 2022-02-10 16:46:00 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:00 +0300 |
commit | 4e4b78bd7b67e2533da4dbb9696374a6d6068e32 (patch) | |
tree | a7a5543d815c451256ece74081d960b4e1d70ec2 /library/cpp/threading/skip_list | |
parent | 5b00ed04a5137a452fa6d3423cb0c9b54ac27408 (diff) | |
download | ydb-4e4b78bd7b67e2533da4dbb9696374a6d6068e32.tar.gz |
Restoring authorship annotation for <vskipin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/threading/skip_list')
-rw-r--r-- | library/cpp/threading/skip_list/compare.h | 36 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/perf/main.cpp | 194 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/perf/ya.make | 22 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/skiplist.cpp | 2 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/skiplist.h | 198 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/skiplist_ut.cpp | 96 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/ut/ya.make | 14 | ||||
-rw-r--r-- | library/cpp/threading/skip_list/ya.make | 16 |
8 files changed, 289 insertions, 289 deletions
diff --git a/library/cpp/threading/skip_list/compare.h b/library/cpp/threading/skip_list/compare.h index ac98b3e1ce..c63003d67f 100644 --- a/library/cpp/threading/skip_list/compare.h +++ b/library/cpp/threading/skip_list/compare.h @@ -1,14 +1,14 @@ -#pragma once - -#include <util/generic/typetraits.h> -#include <util/str_stl.h> - -namespace NThreading { +#pragma once + +#include <util/generic/typetraits.h> +#include <util/str_stl.h> + +namespace NThreading { namespace NImpl { Y_HAS_MEMBER(compare); Y_HAS_MEMBER(Compare); - - template <typename T> + + template <typename T> inline int CompareImpl(const T& l, const T& r) { if (l < r) { return -1; @@ -17,8 +17,8 @@ namespace NThreading { } else { return 0; } - } - + } + template <bool val> struct TSmallCompareSelector { template <typename T> @@ -26,7 +26,7 @@ namespace NThreading { return CompareImpl(l, r); } }; - + template <> struct TSmallCompareSelector<true> { template <typename T> @@ -34,7 +34,7 @@ namespace NThreading { return l.compare(r); } }; - + template <bool val> struct TBigCompareSelector { template <typename T> @@ -51,15 +51,15 @@ namespace NThreading { } }; - template <typename T> + template <typename T> struct TCompareSelector: public TBigCompareSelector<THasCompare<T>::value> { }; } - + //////////////////////////////////////////////////////////////////////////////// // Generic compare function - template <typename T> + template <typename T> inline int Compare(const T& l, const T& r) { return NImpl::TCompareSelector<T>::Compare(l, r); } @@ -72,6 +72,6 @@ namespace NThreading { inline int operator()(const T& l, const T& r) const { return Compare(l, r); } - }; - -} + }; + +} diff --git a/library/cpp/threading/skip_list/perf/main.cpp b/library/cpp/threading/skip_list/perf/main.cpp index 4ad52049e7..4e8d5b4082 100644 --- a/library/cpp/threading/skip_list/perf/main.cpp +++ b/library/cpp/threading/skip_list/perf/main.cpp @@ -1,56 +1,56 @@ #include <library/cpp/threading/skip_list/skiplist.h> - + #include <library/cpp/getopt/small/last_getopt.h> #include <library/cpp/charset/ci_string.h> -#include <util/datetime/base.h> -#include <util/generic/map.h> -#include <util/generic/vector.h> +#include <util/datetime/base.h> +#include <util/generic/map.h> +#include <util/generic/vector.h> #include <functional> -#include <util/memory/pool.h> -#include <util/random/random.h> -#include <util/string/join.h> -#include <util/system/mutex.h> -#include <util/system/thread.h> - -namespace { +#include <util/memory/pool.h> +#include <util/random/random.h> +#include <util/string/join.h> +#include <util/system/mutex.h> +#include <util/system/thread.h> + +namespace { using namespace NThreading; - + //////////////////////////////////////////////////////////////////////////////// - + IOutputStream& LogInfo() { return Cerr << TInstant::Now() << " INFO: "; } - + IOutputStream& LogError() { return Cerr << TInstant::Now() << " ERROR: "; } - + //////////////////////////////////////////////////////////////////////////////// - + struct TListItem { TStringBuf Key; TStringBuf Value; - + TListItem(const TStringBuf& key, const TStringBuf& value) : Key(key) , Value(value) { } - + int Compare(const TListItem& other) const { return Key.compare(other.Key); } }; - + using TListType = TSkipList<TListItem>; - + //////////////////////////////////////////////////////////////////////////////// - + class TRandomData { private: TVector<char> Buffer; - + public: TRandomData() : Buffer(1024 * 1024) @@ -59,34 +59,34 @@ namespace { Buffer[i] = RandomNumber<char>(); } } - + TStringBuf GetString(size_t len) const { size_t start = RandomNumber(Buffer.size() - len); return TStringBuf(&Buffer[start], len); - } - + } + TStringBuf GetString(size_t min, size_t max) const { return GetString(min + RandomNumber(max - min)); } }; - + //////////////////////////////////////////////////////////////////////////////// - + class TWorkerThread: public ISimpleThread { private: std::function<void()> Func; TDuration Time; - + public: TWorkerThread(std::function<void()> func) : Func(func) { } - + TDuration GetTime() const { return Time; } - + private: void* ThreadProc() noexcept override { TInstant started = TInstant::Now(); @@ -95,33 +95,33 @@ namespace { return nullptr; } }; - + inline TAutoPtr<TWorkerThread> StartThread(std::function<void()> func) { TAutoPtr<TWorkerThread> thread = new TWorkerThread(func); thread->Start(); return thread; - } - + } + //////////////////////////////////////////////////////////////////////////////// - + typedef std::function<void()> TTestFunc; - + struct TTest { TString Name; TTestFunc Func; - + TTest() { } - + TTest(const TString& name, const TTestFunc& func) : Name(name) , Func(func) { } }; - + //////////////////////////////////////////////////////////////////////////////// - + class TTestSuite { private: size_t Iterations = 1000000; @@ -130,72 +130,72 @@ namespace { size_t NumReaders = 4; size_t NumWriters = 1; size_t BatchSize = 20; - + TMemoryPool MemoryPool; TListType List; TMutex Mutex; TRandomData Random; - + TMap<TCiString, TTest> AllTests; TVector<TTest> Tests; - + public: TTestSuite() : MemoryPool(64 * 1024) , List(MemoryPool) { } - + bool Init(int argc, const char* argv[]) { TVector<TString> tests; try { NLastGetopt::TOpts opts; opts.AddHelpOption(); - + #define OPTION(opt, x) \ opts.AddLongOption(opt, #x) \ .Optional() \ .DefaultValue(ToString(x)) \ .StoreResult(&x) // end of OPTION - + OPTION('i', Iterations); OPTION('k', KeyLen); OPTION('v', ValueLen); OPTION('r', NumReaders); OPTION('w', NumWriters); OPTION('b', BatchSize); - -#undef OPTION - + +#undef OPTION + NLastGetopt::TOptsParseResultException optsRes(&opts, argc, argv); for (const auto& opt : opts.Opts_) { const NLastGetopt::TOptParseResult* r = optsRes.FindOptParseResult(opt.Get(), true); if (r) { LogInfo() << "[-" << opt->GetChar() << "] " << opt->GetName() << ": " << r->Back() << Endl; } - } + } tests = optsRes.GetFreeArgs(); } catch (...) { LogError() << CurrentExceptionMessage() << Endl; return false; - } - -#define TEST(type) \ + } + +#define TEST(type) \ AddTest(#type, std::bind(&TTestSuite::Y_CAT(TEST_, type), this)) // end of TEST - + TEST(Clear); TEST(InsertRandom); TEST(InsertSequential); TEST(InsertSequentialSimple); TEST(LookupRandom); TEST(Concurrent); - -#undef TEST - + +#undef TEST + if (tests.empty()) { LogError() << "no tests specified, choose from: " << PrintTests() << Endl; - return false; - } + return false; + } for (size_t i = 0; i < tests.size(); ++i) { if (!AllTests.contains(tests[i])) { @@ -206,13 +206,13 @@ namespace { } return true; - } - + } + void Run() { -#if !defined(NDEBUG) +#if !defined(NDEBUG) LogInfo() << "*** DEBUG build! ***" << Endl; -#endif - +#endif + for (const TTest& test : Tests) { LogInfo() << "Starting test " << test.Name << Endl; @@ -224,7 +224,7 @@ namespace { << " failed: " << CurrentExceptionMessage() << Endl; } - + LogInfo() << "List size = " << List.GetSize() << Endl; TDuration duration = TInstant::Now() - started; @@ -234,31 +234,31 @@ namespace { << Endl; LogInfo() << "Finished test " << test.Name << Endl; } - } - + } + private: void AddTest(const char* name, TTestFunc func) { AllTests[name] = TTest(name, func); } - + TString PrintTests() const { TVector<TString> names; for (const auto& it : AllTests) { names.push_back(it.first); } return JoinSeq(", ", names); - } - + } + void TEST_Clear() { List.Clear(); } - + void TEST_InsertRandom() { for (size_t i = 0; i < Iterations; ++i) { List.Insert(TListItem(Random.GetString(KeyLen), Random.GetString(ValueLen))); } - } - + } + void TEST_InsertSequential() { TString key; for (size_t i = 0; i < Iterations;) { @@ -269,9 +269,9 @@ namespace { key.append((char)j); List.Insert(TListItem(key, Random.GetString(ValueLen))); } - } - } - + } + } + void TEST_InsertSequentialSimple() { for (size_t i = 0; i < Iterations; ++i) { List.Insert(TListItem(Random.GetString(KeyLen), Random.GetString(ValueLen))); @@ -282,11 +282,11 @@ namespace { for (size_t i = 0; i < Iterations; ++i) { List.SeekTo(TListItem(Random.GetString(KeyLen), TStringBuf())); } - } - + } + void TEST_Concurrent() { LogInfo() << "starting producers..." << Endl; - + TVector<TAutoPtr<TWorkerThread>> producers(NumWriters); for (size_t i1 = 0; i1 < producers.size(); ++i1) { producers[i1] = StartThread([&] { @@ -304,9 +304,9 @@ namespace { << Endl; }); } - + LogInfo() << "starting consumers..." << Endl; - + TVector<TAutoPtr<TWorkerThread>> consumers(NumReaders); for (size_t i1 = 0; i1 < consumers.size(); ++i1) { consumers[i1] = StartThread([&] { @@ -321,42 +321,42 @@ namespace { << Endl; }); } - + LogInfo() << "wait for producers..." << Endl; - + TDuration producerTime; for (size_t i = 0; i < producers.size(); ++i) { producers[i]->Join(); producerTime += producers[i]->GetTime(); } - + LogInfo() << "wait for consumers..." << Endl; - + TDuration consumerTime; for (size_t i = 0; i < consumers.size(); ++i) { consumers[i]->Join(); consumerTime += consumers[i]->GetTime(); } - + LogInfo() << "average producer time: " << producerTime.SecondsFloat() / producers.size() << " seconds" << Endl; - + LogInfo() << "average consumer time: " << consumerTime.SecondsFloat() / consumers.size() << " seconds" << Endl; } }; - + } - -//////////////////////////////////////////////////////////////////////////////// - + +//////////////////////////////////////////////////////////////////////////////// + int main(int argc, const char* argv[]) { - TTestSuite suite; - if (!suite.Init(argc, argv)) { - return -1; - } - suite.Run(); - return 0; -} + TTestSuite suite; + if (!suite.Init(argc, argv)) { + return -1; + } + suite.Run(); + return 0; +} diff --git a/library/cpp/threading/skip_list/perf/ya.make b/library/cpp/threading/skip_list/perf/ya.make index 01bfafa404..d64a58a60e 100644 --- a/library/cpp/threading/skip_list/perf/ya.make +++ b/library/cpp/threading/skip_list/perf/ya.make @@ -1,15 +1,15 @@ -PROGRAM(skiplist-perf) - +PROGRAM(skiplist-perf) + OWNER(g:rtmr) - -PEERDIR( + +PEERDIR( library/cpp/charset library/cpp/getopt/small library/cpp/threading/skip_list -) - -SRCS( - main.cpp -) - -END() +) + +SRCS( + main.cpp +) + +END() diff --git a/library/cpp/threading/skip_list/skiplist.cpp b/library/cpp/threading/skip_list/skiplist.cpp index c6e98816fb..386b9546d4 100644 --- a/library/cpp/threading/skip_list/skiplist.cpp +++ b/library/cpp/threading/skip_list/skiplist.cpp @@ -1 +1 @@ -#include "skiplist.h" +#include "skiplist.h" diff --git a/library/cpp/threading/skip_list/skiplist.h b/library/cpp/threading/skip_list/skiplist.h index 914a7c6ee7..054a1b10b9 100644 --- a/library/cpp/threading/skip_list/skiplist.h +++ b/library/cpp/threading/skip_list/skiplist.h @@ -1,69 +1,69 @@ -#pragma once - -#include "compare.h" - -#include <util/generic/algorithm.h> -#include <util/generic/noncopyable.h> -#include <util/generic/typetraits.h> -#include <util/memory/pool.h> -#include <util/random/random.h> -#include <util/system/atomic.h> - -namespace NThreading { +#pragma once + +#include "compare.h" + +#include <util/generic/algorithm.h> +#include <util/generic/noncopyable.h> +#include <util/generic/typetraits.h> +#include <util/memory/pool.h> +#include <util/random/random.h> +#include <util/system/atomic.h> + +namespace NThreading { //////////////////////////////////////////////////////////////////////////////// - + class TNopCounter { protected: template <typename T> void OnInsert(const T&) { } - + template <typename T> void OnUpdate(const T&) { } - + void Reset() { } }; - + //////////////////////////////////////////////////////////////////////////////// - + class TSizeCounter { - private: + private: size_t Size; - - public: + + public: TSizeCounter() : Size(0) - { - } - + { + } + size_t GetSize() const { return Size; - } - + } + protected: template <typename T> void OnInsert(const T&) { ++Size; - } - + } + template <typename T> void OnUpdate(const T&) { - } - + } + void Reset() { Size = 0; - } - }; - + } + }; + //////////////////////////////////////////////////////////////////////////////// // Append-only concurrent skip-list // // Readers do not require any synchronization. // Writers should be externally synchronized. // Nodes will be allocated using TMemoryPool instance. - + template < typename T, typename TComparer = TCompare<T>, @@ -104,41 +104,41 @@ namespace NThreading { } }; - public: + public: class TIterator { private: const TSkipList* List; const TNode* Node; - + public: TIterator() : List(nullptr) , Node(nullptr) { } - + TIterator(const TSkipList* list, const TNode* node) : List(list) , Node(node) { } - + TIterator(const TIterator& other) : List(other.List) , Node(other.Node) { } - + TIterator& operator=(const TIterator& other) { List = other.List; Node = other.Node; return *this; } - + void Next() { Node = Node ? Node->GetNext(0) : nullptr; - } - + } + // much less efficient than Next as our list is single-linked void Prev() { if (Node) { @@ -146,34 +146,34 @@ namespace NThreading { Node = (node != List->Head ? node : nullptr); } } - + void Reset() { Node = nullptr; } - + bool IsValid() const { return Node != nullptr; } - + const T& GetValue() const { Y_ASSERT(IsValid()); return Node->GetValue(); } }; - + private: TAllocator& Allocator; TComparer Comparer; - + TNode* Head; TAtomic Height; TCounter Counter; - + TNode* Prev[MaxHeight]; - + template <typename TValue> using TComparerReturnType = std::invoke_result_t<TComparer, const T&, const TValue&>; - + public: TSkipList(TAllocator& allocator, const TComparer& comparer = TComparer()) : Allocator(allocator) @@ -181,28 +181,28 @@ namespace NThreading { { Init(); } - + ~TSkipList() { CallDtors(); } - + void Clear() { CallDtors(); Allocator.ClearKeepFirstChunk(); Init(); - } - + } + bool Insert(T value) { TNode* node = PrepareInsert(value); if (Y_UNLIKELY(node && Compare(node, value) == 0)) { // we do not allow duplicates return false; - } + } node = DoInsert(std::move(value)); TCounter::OnInsert(node->GetValue()); return true; - } - + } + template <typename TInsertAction, typename TUpdateAction> bool Insert(const T& value, TInsertAction insert, TUpdateAction update) { TNode* node = PrepareInsert(value); @@ -218,27 +218,27 @@ namespace NThreading { TCounter::OnInsert(node->GetValue()); return true; } - + template <typename TValue> bool Contains(const TValue& value) const { TNode* node = FindGreaterThanOrEqual(value); return node && Compare(node, value) == 0; } - + TIterator SeekToFirst() const { return TIterator(this, FindFirst()); } - + TIterator SeekToLast() const { TNode* last = FindLast(); return TIterator(this, last != Head ? last : nullptr); } - + template <typename TValue> TIterator SeekTo(const TValue& value) const { return TIterator(this, FindGreaterThanOrEqual(value)); - } - + } + private: static int RandomHeight() { int height = 1; @@ -247,7 +247,7 @@ namespace NThreading { } return height; } - + void Init() { Head = AllocateRootNode(); Height = 1; @@ -256,8 +256,8 @@ namespace NThreading { for (int i = 0; i < MaxHeight; ++i) { Prev[i] = Head; } - } - + } + void CallDtors() { if (!TTypeTraits<T>::IsPod) { // we should explicitly call destructors for our nodes @@ -267,56 +267,56 @@ namespace NThreading { node->~TNode(); node = next; } - } - } - + } + } + TNode* AllocateRootNode() { size_t size = sizeof(TNode) + sizeof(TNode*) * MaxHeight; void* buffer = Allocator.Allocate(size); memset(buffer, 0, size); return static_cast<TNode*>(buffer); } - + TNode* AllocateNode(T&& value, int height) { size_t size = sizeof(TNode) + sizeof(TNode*) * height; void* buffer = Allocator.Allocate(size); memset(buffer, 0, size); return new (buffer) TNode(std::move(value)); } - + TNode* FindFirst() const { return Head->GetNext(0); } - + TNode* FindLast() const { TNode* node = Head; int height = AtomicGet(Height) - 1; - + while (true) { TNode* next = node->GetNext(height); if (next) { node = next; continue; } - + if (height) { --height; } else { return node; } - } - } - + } + } + template <typename TValue> TComparerReturnType<TValue> Compare(const TNode* node, const TValue& value) const { return Comparer(node->GetValue(), value); } - + template <typename TValue> TNode* FindLessThan(const TValue& value, TNode** links) const { TNode* node = Head; int height = AtomicGet(Height) - 1; - + TNode* prev = nullptr; while (true) { TNode* next = node->GetNext(height); @@ -326,27 +326,27 @@ namespace NThreading { node = next; continue; } - } - + } + if (links) { // collect links from upper levels links[height] = node; } - + if (height) { prev = next; --height; } else { return node; } - } - } - + } + } + template <typename TValue> TNode* FindGreaterThanOrEqual(const TValue& value) const { TNode* node = Head; int height = AtomicGet(Height) - 1; - + TNode* prev = nullptr; while (true) { TNode* next = node->GetNext(height); @@ -359,29 +359,29 @@ namespace NThreading { if (cmp == 0) { return next; } - } + } if (height) { prev = next; --height; } else { - return next; - } - } + return next; + } + } } - + TNode* PrepareInsert(const T& value) { TNode* prev = Prev[0]; TNode* next = prev->GetNext(0); if ((prev == Head || Compare(prev, value) < 0) && (next == nullptr || Compare(next, value) >= 0)) { // avoid seek in case of sequential insert - } else { + } else { prev = FindLessThan(value, Prev); next = prev->GetNext(0); - } + } return next; - } - + } + TNode* DoInsert(T&& value) { // choose level to place new node int currentHeight = AtomicGet(Height); @@ -392,17 +392,17 @@ namespace NThreading { Prev[i] = Head; } AtomicSet(Height, height); - } - + } + TNode* node = AllocateNode(std::move(value), height); node->Link(height, Prev); - + // keep last inserted node to optimize sequential inserts for (int i = 0; i < height; i++) { Prev[i] = node; } return node; - } + } }; - + } diff --git a/library/cpp/threading/skip_list/skiplist_ut.cpp b/library/cpp/threading/skip_list/skiplist_ut.cpp index 52fcffda66..e7d0b62873 100644 --- a/library/cpp/threading/skip_list/skiplist_ut.cpp +++ b/library/cpp/threading/skip_list/skiplist_ut.cpp @@ -1,91 +1,91 @@ -#include "skiplist.h" - +#include "skiplist.h" + #include <library/cpp/testing/unittest/registar.h> - -namespace NThreading { + +namespace NThreading { namespace { struct TTestObject { static size_t Count; int Tag; - + TTestObject(int tag) : Tag(tag) { ++Count; } - + TTestObject(const TTestObject& other) : Tag(other.Tag) { ++Count; } - + ~TTestObject() { --Count; } - + bool operator<(const TTestObject& other) const { return Tag < other.Tag; } }; - + size_t TTestObject::Count = 0; - - } - + + } + //////////////////////////////////////////////////////////////////////////////// - + Y_UNIT_TEST_SUITE(TSkipListTest) { Y_UNIT_TEST(ShouldBeEmptyAfterCreation) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT_EQUAL(list.GetSize(), 0); } - + Y_UNIT_TEST(ShouldAllowInsertion) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(12345678)); UNIT_ASSERT_EQUAL(list.GetSize(), 1); } - + Y_UNIT_TEST(ShouldNotAllowDuplicates) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(12345678)); UNIT_ASSERT_EQUAL(list.GetSize(), 1); - + UNIT_ASSERT(!list.Insert(12345678)); UNIT_ASSERT_EQUAL(list.GetSize(), 1); } - + Y_UNIT_TEST(ShouldContainInsertedItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(12345678)); UNIT_ASSERT(list.Contains(12345678)); } - + Y_UNIT_TEST(ShouldNotContainNotInsertedItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(12345678)); UNIT_ASSERT(!list.Contains(87654321)); } - + Y_UNIT_TEST(ShouldIterateAllItems) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + for (int i = 8; i > 0; --i) { UNIT_ASSERT(list.Insert(i)); } - + TSkipList<int>::TIterator it = list.SeekToFirst(); for (int i = 1; i <= 8; ++i) { UNIT_ASSERT(it.IsValid()); @@ -94,15 +94,15 @@ namespace NThreading { } UNIT_ASSERT(!it.IsValid()); } - + Y_UNIT_TEST(ShouldIterateAllItemsInReverseDirection) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + for (int i = 8; i > 0; --i) { UNIT_ASSERT(list.Insert(i)); } - + TSkipList<int>::TIterator it = list.SeekToLast(); for (int i = 8; i > 0; --i) { UNIT_ASSERT(it.IsValid()); @@ -111,75 +111,75 @@ namespace NThreading { } UNIT_ASSERT(!it.IsValid()); } - + Y_UNIT_TEST(ShouldSeekToFirstItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + for (int i = 1; i < 10; ++i) { UNIT_ASSERT(list.Insert(i)); } - + TSkipList<int>::TIterator it = list.SeekToFirst(); UNIT_ASSERT(it.IsValid()); UNIT_ASSERT_EQUAL(it.GetValue(), 1); } - + Y_UNIT_TEST(ShouldSeekToLastItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + for (int i = 1; i < 10; ++i) { UNIT_ASSERT(list.Insert(i)); } - + TSkipList<int>::TIterator it = list.SeekToLast(); UNIT_ASSERT(it.IsValid()); UNIT_ASSERT_EQUAL(it.GetValue(), 9); } - + Y_UNIT_TEST(ShouldSeekToExistingItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(12345678)); - + TSkipList<int>::TIterator it = list.SeekTo(12345678); UNIT_ASSERT(it.IsValid()); } - + Y_UNIT_TEST(ShouldSeekAfterMissedItem) { TMemoryPool pool(1024); TSkipList<int> list(pool); - + UNIT_ASSERT(list.Insert(100)); UNIT_ASSERT(list.Insert(300)); - + TSkipList<int>::TIterator it = list.SeekTo(200); UNIT_ASSERT(it.IsValid()); UNIT_ASSERT_EQUAL(it.GetValue(), 300); - + it.Prev(); UNIT_ASSERT(it.IsValid()); UNIT_ASSERT_EQUAL(it.GetValue(), 100); } - + Y_UNIT_TEST(ShouldCallDtorsOfNonPodTypes) { UNIT_ASSERT(!TTypeTraits<TTestObject>::IsPod); UNIT_ASSERT_EQUAL(TTestObject::Count, 0); - + { TMemoryPool pool(1024); TSkipList<TTestObject> list(pool); - + UNIT_ASSERT(list.Insert(TTestObject(1))); UNIT_ASSERT(list.Insert(TTestObject(2))); - + UNIT_ASSERT_EQUAL(TTestObject::Count, 2); } UNIT_ASSERT_EQUAL(TTestObject::Count, 0); } - } - + } + } diff --git a/library/cpp/threading/skip_list/ut/ya.make b/library/cpp/threading/skip_list/ut/ya.make index 704a31e9a2..ae07423e71 100644 --- a/library/cpp/threading/skip_list/ut/ya.make +++ b/library/cpp/threading/skip_list/ut/ya.make @@ -1,9 +1,9 @@ UNITTEST_FOR(library/cpp/threading/skip_list) - + OWNER(g:rtmr) - -SRCS( - skiplist_ut.cpp -) - -END() + +SRCS( + skiplist_ut.cpp +) + +END() diff --git a/library/cpp/threading/skip_list/ya.make b/library/cpp/threading/skip_list/ya.make index d338aeae2b..923fcb3566 100644 --- a/library/cpp/threading/skip_list/ya.make +++ b/library/cpp/threading/skip_list/ya.make @@ -1,9 +1,9 @@ -LIBRARY() - +LIBRARY() + OWNER(g:rtmr) - -SRCS( - skiplist.cpp -) - -END() + +SRCS( + skiplist.cpp +) + +END() |