aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/threading/skip_list
diff options
context:
space:
mode:
authorvskipin <vskipin@yandex-team.ru>2022-02-10 16:46:00 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:00 +0300
commit4e4b78bd7b67e2533da4dbb9696374a6d6068e32 (patch)
treea7a5543d815c451256ece74081d960b4e1d70ec2 /library/cpp/threading/skip_list
parent5b00ed04a5137a452fa6d3423cb0c9b54ac27408 (diff)
downloadydb-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.h36
-rw-r--r--library/cpp/threading/skip_list/perf/main.cpp194
-rw-r--r--library/cpp/threading/skip_list/perf/ya.make22
-rw-r--r--library/cpp/threading/skip_list/skiplist.cpp2
-rw-r--r--library/cpp/threading/skip_list/skiplist.h198
-rw-r--r--library/cpp/threading/skip_list/skiplist_ut.cpp96
-rw-r--r--library/cpp/threading/skip_list/ut/ya.make14
-rw-r--r--library/cpp/threading/skip_list/ya.make16
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()