// 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"); } 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; }