Skip to content
Snippets Groups Projects
SimpleUrcuTest.cpp 2.42 KiB
Newer Older
  • Learn to ignore specific revisions
  • // 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;
    }