Merge branch 'tests' into dev
This commit is contained in:
commit
a1fc3244ef
@ -352,11 +352,13 @@ public:
|
|||||||
return succs[0]->value();
|
return succs[0]->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_next()
|
// WRONG THIS CAN POSSIBLY NOT BE TRUE IF SOMEONE JUST AFTER THIS REMOVE
|
||||||
{
|
// ELEMENT AFTER THIS ONE.
|
||||||
assert(succs[0] != nullptr);
|
// bool has_next()
|
||||||
return succs[0].forward(0) != nullptr;
|
// {
|
||||||
}
|
// assert(succs[0] != nullptr);
|
||||||
|
// return succs[0].forward(0) != nullptr;
|
||||||
|
// }
|
||||||
|
|
||||||
bool has_value() { return succs[0] != nullptr; }
|
bool has_value() { return succs[0] != nullptr; }
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "data_structures/bitset/dynamic_bitset.hpp"
|
||||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||||
#include "data_structures/concurrent/concurrent_multimap.hpp"
|
#include "data_structures/concurrent/concurrent_multimap.hpp"
|
||||||
#include "data_structures/concurrent/concurrent_multiset.hpp"
|
#include "data_structures/concurrent/concurrent_multiset.hpp"
|
||||||
@ -106,6 +107,14 @@ void check_zero(size_t key_range, long array[], const char *str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_set(DynamicBitset<> &db, std::vector<bool> &set)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < set.size(); i++) {
|
||||||
|
permanent_assert(!(set[i] ^ db.at(i)),
|
||||||
|
"Set constraints aren't fullfilled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Checks multiIterator and iterator guarantees
|
// Checks multiIterator and iterator guarantees
|
||||||
void check_multi_iterator(multimap_t::Accessor &accessor, size_t key_range,
|
void check_multi_iterator(multimap_t::Accessor &accessor, size_t key_range,
|
||||||
long set[])
|
long set[])
|
||||||
@ -164,6 +173,25 @@ run(size_t threads_no, S &skiplist,
|
|||||||
return futures;
|
return futures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Runs given function in threads_no threads and returns vector of futures for
|
||||||
|
// there
|
||||||
|
// results.
|
||||||
|
template <class R>
|
||||||
|
std::vector<std::future<std::pair<size_t, R>>> run(size_t threads_no,
|
||||||
|
std::function<R(size_t)> f)
|
||||||
|
{
|
||||||
|
std::vector<std::future<std::pair<size_t, R>>> futures;
|
||||||
|
|
||||||
|
for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) {
|
||||||
|
std::packaged_task<std::pair<size_t, R>()> task([f, thread_i]() {
|
||||||
|
return std::pair<size_t, R>(thread_i, f(thread_i));
|
||||||
|
}); // wrap the function
|
||||||
|
futures.push_back(task.get_future()); // get a future
|
||||||
|
std::thread(std::move(task)).detach();
|
||||||
|
}
|
||||||
|
return futures;
|
||||||
|
}
|
||||||
|
|
||||||
// Collects all data from futures.
|
// Collects all data from futures.
|
||||||
template <class R>
|
template <class R>
|
||||||
auto collect(std::vector<std::future<R>> &collect)
|
auto collect(std::vector<std::future<R>> &collect)
|
||||||
@ -175,6 +203,19 @@ auto collect(std::vector<std::future<R>> &collect)
|
|||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<bool> collect_set(
|
||||||
|
std::vector<std::future<std::pair<size_t, std::vector<bool>>>> &&futures)
|
||||||
|
{
|
||||||
|
std::vector<bool> set;
|
||||||
|
for (auto &data : collect(futures)) {
|
||||||
|
set.resize(data.second.size());
|
||||||
|
for (int i = 0; i < data.second.size(); i++) {
|
||||||
|
set[i] = set[i] | data.second[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns object which tracs in owned which (key,data) where added and
|
// Returns object which tracs in owned which (key,data) where added and
|
||||||
// downcounts.
|
// downcounts.
|
||||||
template <class K, class D, class S>
|
template <class K, class D, class S>
|
||||||
|
39
tests/concurrent/dynamic_bitset.cpp
Normal file
39
tests/concurrent/dynamic_bitset.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define THREADS_NO 8
|
||||||
|
constexpr size_t op_per_thread = 1e5;
|
||||||
|
constexpr size_t bit_part_len = 2;
|
||||||
|
constexpr size_t no_slots = 1e4;
|
||||||
|
constexpr size_t key_range = no_slots * THREADS_NO * bit_part_len;
|
||||||
|
constexpr size_t no_sets_per_clear = 2;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
DynamicBitset<> db;
|
||||||
|
auto seted =
|
||||||
|
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
|
||||||
|
auto rand = rand_gen(no_slots);
|
||||||
|
auto clear_op = rand_gen_bool(no_sets_per_clear);
|
||||||
|
std::vector<bool> set(key_range);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < op_per_thread; i++) {
|
||||||
|
size_t num =
|
||||||
|
rand() * THREADS_NO * bit_part_len + index * bit_part_len;
|
||||||
|
|
||||||
|
if (clear_op()) {
|
||||||
|
db.clear(num, bit_part_len);
|
||||||
|
for (int j = 0; j < bit_part_len; j++) {
|
||||||
|
set[num + j] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
db.set(num, bit_part_len);
|
||||||
|
for (int j = 0; j < bit_part_len; j++)
|
||||||
|
set[num + j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}));
|
||||||
|
|
||||||
|
check_set(db, seted);
|
||||||
|
}
|
52
tests/concurrent/dynamic_bitset_clear_n.cpp
Normal file
52
tests/concurrent/dynamic_bitset_clear_n.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define THREADS_NO 4
|
||||||
|
constexpr size_t op_per_thread = 1e5;
|
||||||
|
constexpr size_t up_border_bit_set_pow2 = 3;
|
||||||
|
constexpr size_t key_range =
|
||||||
|
op_per_thread * THREADS_NO * (1 << up_border_bit_set_pow2) * 2;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
DynamicBitset<> db;
|
||||||
|
auto seted =
|
||||||
|
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
|
||||||
|
auto rand = rand_gen(key_range);
|
||||||
|
auto rand_len = rand_gen(up_border_bit_set_pow2);
|
||||||
|
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < op_per_thread; i++) {
|
||||||
|
auto len = 1 << rand_len();
|
||||||
|
size_t num = (rand() / len) * len;
|
||||||
|
db.set(num, len);
|
||||||
|
for (int j = 0; j < len; j++)
|
||||||
|
set[num + j] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}));
|
||||||
|
|
||||||
|
auto cleared =
|
||||||
|
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
|
||||||
|
auto rand = rand_gen(key_range);
|
||||||
|
auto rand_len = rand_gen(up_border_bit_set_pow2);
|
||||||
|
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < op_per_thread; i++) {
|
||||||
|
auto len = 1 << rand_len();
|
||||||
|
size_t num = (rand() / len) * len;
|
||||||
|
for (int j = 0; j < len; j++) {
|
||||||
|
set[num + j] = set[num + j] | db.at(num + j);
|
||||||
|
}
|
||||||
|
db.clear(num, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < seted.size(); i++) {
|
||||||
|
seted[i] = seted[i] & (!cleared[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_set(db, seted);
|
||||||
|
}
|
24
tests/concurrent/dynamic_bitset_set.cpp
Normal file
24
tests/concurrent/dynamic_bitset_set.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define THREADS_NO 8
|
||||||
|
constexpr size_t op_per_thread = 1e5;
|
||||||
|
constexpr size_t key_range = op_per_thread * THREADS_NO * 3;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
DynamicBitset<> db;
|
||||||
|
auto set = collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
|
||||||
|
auto rand = rand_gen(key_range);
|
||||||
|
std::vector<bool> set(key_range);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < op_per_thread; i++) {
|
||||||
|
size_t num = rand();
|
||||||
|
db.set(num);
|
||||||
|
set[num] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}));
|
||||||
|
|
||||||
|
check_set(db, set);
|
||||||
|
}
|
29
tests/concurrent/dynamic_bitset_set_n.cpp
Normal file
29
tests/concurrent/dynamic_bitset_set_n.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define THREADS_NO 4
|
||||||
|
constexpr size_t op_per_thread = 1e5;
|
||||||
|
constexpr size_t up_border_bit_set_pow2 = 3;
|
||||||
|
constexpr size_t key_range =
|
||||||
|
op_per_thread * THREADS_NO * (1 << up_border_bit_set_pow2) * 2;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
DynamicBitset<> db;
|
||||||
|
auto set = collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
|
||||||
|
auto rand = rand_gen(key_range);
|
||||||
|
auto rand_len = rand_gen(up_border_bit_set_pow2);
|
||||||
|
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < op_per_thread; i++) {
|
||||||
|
auto len = 1 << rand_len();
|
||||||
|
size_t num = (rand() / len) * len;
|
||||||
|
db.set(num, len);
|
||||||
|
for (int j = 0; j < len; j++)
|
||||||
|
set[num + j] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}));
|
||||||
|
|
||||||
|
check_set(db, set);
|
||||||
|
}
|
@ -1,23 +1,20 @@
|
|||||||
#include <iostream>
|
#include <array>
|
||||||
#include <deque>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <array>
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "communication/bolt/v1/transport/chunked_decoder.hpp"
|
#include "communication/bolt/v1/transport/chunked_decoder.hpp"
|
||||||
|
|
||||||
using byte = unsigned char;
|
using byte = unsigned char;
|
||||||
|
|
||||||
void print_hex(byte x)
|
void print_hex(byte x) { printf("%02X ", static_cast<byte>(x)); }
|
||||||
{
|
|
||||||
printf("%02X ", static_cast<byte>(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
class DummyStream
|
class DummyStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void write(const byte* values, size_t n)
|
void write(const byte *values, size_t n)
|
||||||
{
|
{
|
||||||
data.insert(data.end(), values, values + n);
|
data.insert(data.end(), values, values + n);
|
||||||
}
|
}
|
||||||
@ -28,11 +25,11 @@ public:
|
|||||||
using Decoder = bolt::ChunkedDecoder<DummyStream>;
|
using Decoder = bolt::ChunkedDecoder<DummyStream>;
|
||||||
|
|
||||||
std::vector<byte> chunks[] = {
|
std::vector<byte> chunks[] = {
|
||||||
{0x00,0x08,'A',' ','q','u','i','c','k',' ',0x00,0x06,'b','r','o','w','n',' '},
|
{0x00, 0x08, 'A', ' ', 'q', 'u', 'i', 'c', 'k', ' ', 0x00, 0x06, 'b', 'r',
|
||||||
{0x00,0x0A,'f','o','x',' ','j','u','m','p','s',' '},
|
'o', 'w', 'n', ' '},
|
||||||
{0x00,0x07,'o','v','e','r',' ','a',' '},
|
{0x00, 0x0A, 'f', 'o', 'x', ' ', 'j', 'u', 'm', 'p', 's', ' '},
|
||||||
{0x00,0x08,'l','a','z','y',' ','d','o','g',0x00,0x00}
|
{0x00, 0x07, 'o', 'v', 'e', 'r', ' ', 'a', ' '},
|
||||||
};
|
{0x00, 0x08, 'l', 'a', 'z', 'y', ' ', 'd', 'o', 'g', 0x00, 0x00}};
|
||||||
|
|
||||||
static constexpr size_t N = std::extent<decltype(chunks)>::value;
|
static constexpr size_t N = std::extent<decltype(chunks)>::value;
|
||||||
|
|
||||||
|
53
tests/unit/skiplistset.cpp
Normal file
53
tests/unit/skiplistset.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "data_structures/concurrent/concurrent_set.hpp"
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
void print_skiplist(const ConcurrentSet<int>::Accessor &skiplist)
|
||||||
|
{
|
||||||
|
cout << "---- skiplist set now has: ";
|
||||||
|
|
||||||
|
for (auto &item : skiplist)
|
||||||
|
cout << item << ", ";
|
||||||
|
|
||||||
|
cout << "----" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
ConcurrentSet<int> set;
|
||||||
|
auto accessor = set.access();
|
||||||
|
|
||||||
|
cout << std::boolalpha;
|
||||||
|
|
||||||
|
cout << "added non-existing 1? (true) " << accessor.insert(1).second
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
cout << "added already existing 1? (false) " << accessor.insert(1).second
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
accessor.insert(2);
|
||||||
|
print_skiplist(accessor);
|
||||||
|
|
||||||
|
cout << "item 3 doesn't exist? (true) "
|
||||||
|
<< (accessor.find(3) == accessor.end()) << endl;
|
||||||
|
|
||||||
|
cout << "item 3 exists? (false) " << accessor.contains(3) << endl;
|
||||||
|
|
||||||
|
cout << "item 2 exists? (true) " << (accessor.find(2) != accessor.end())
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
cout << "at item 2 is? 2 " << *accessor.find(2) << endl;
|
||||||
|
|
||||||
|
cout << "removed existing 1? (true) " << accessor.remove(1) << endl;
|
||||||
|
cout << "removed non-existing 3? (false) " << accessor.remove(3) << endl;
|
||||||
|
|
||||||
|
accessor.insert(1);
|
||||||
|
accessor.insert(4);
|
||||||
|
|
||||||
|
print_skiplist(accessor);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user