Newer
Older
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2020 Florian Fischer
#include <urcu.h> // for rcu_read_lock, rcu_read_unlock
#include <urcu/rculfhash.h> // for RCU lock-free hash table
#include <algorithm> // for find
#include <cstdlib> // for exit, EXIT_FAILURE, EXIT_SUC...
#include <functional> // for hash
#include <iostream> // for hash
#include <vector> // for vector
#include "Common.hpp" // for DIE
#include "CountingPrivateSemaphore.hpp" // for CPS
#include "Fiber.hpp" // for Fiber
#include "Runtime.hpp" // for Runtime
#include "emper.hpp" // for spawn
struct node {
int value;
struct cds_lfht_node node; /* Chaining in hash table */
};
using node_t = struct node;
auto main() -> int {
Runtime runtime;
struct cds_lfht* ht;
std::vector<int> values = {
-5, 42, 42, 36, 24,
}; /* 42 is duplicated */
// Allocate new hash table.
ht = cds_lfht_new(1, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, nullptr);
if (!ht) {
DIE_MSG("Error allocating hash table");
}
Fiber* verifier = Fiber::from([&]() {
CPS cps;
for (auto& value : values) {
// add each value to the hash table
spawn(
[&ht, value] {
auto* node = reinterpret_cast<node_t*>(malloc(sizeof(node_t)));
if (!node) {
DIE_MSG_ERRNO("allocating node failed");
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
}
cds_lfht_node_init(&node->node);
node->value = value;
size_t hash = std::hash<int>{}(value);
rcu_read_lock();
cds_lfht_add(ht, hash, &node->node);
rcu_read_unlock();
},
cps);
}
// Wait for the adders to finish
cps.wait();
// Verify the content of the hash table.
// Iterate over each hash table node.
// Iteration needs to be performed within RCU read-side critical section.
struct cds_lfht_iter iter;
node_t* node;
rcu_read_lock();
size_t i = 0;
cds_lfht_for_each_entry(ht, &iter, node, node) {
++i;
auto it = std::find(values.begin(), values.end(), node->value);
if (it == values.end()) {
std::cerr << "value: " << node->value << " not found in cds_lfht" << std::endl;
exit(EXIT_FAILURE);
}
}
rcu_read_unlock();
if (i != values.size()) {
std::cerr << "number of values in cds_lfht: " << i
<< " differ number of added ones: " << values.size() << std::endl;
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
});
runtime.scheduleFromAnywhere(*verifier);
runtime.waitUntilFinished();
return EXIT_FAILURE;
}