uatomic/x86: Remove redundant memory barriers
[urcu.git] / doc / examples / rculfhash / cds_lfht_add_replace.c
CommitLineData
1c87adb3
MJ
1// SPDX-FileCopyrightText: 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2//
3// SPDX-License-Identifier: MIT
4
34b3f359 5/*
34b3f359
MD
6 * This example shows how to add nodes into a RCU lock-free hash table
7 * with cds_lfht_add_replace(), which replaces existing nodes with the
8 * same key if found.
9 * We use a "seqnum" field to show which node is staying in the hash
10 * table. This hash table requires using a RCU scheme.
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <time.h>
16
b9050d91 17#include <urcu/urcu-memb.h> /* RCU flavor */
34b3f359
MD
18#include <urcu/rculfhash.h> /* RCU Lock-free hash table */
19#include <urcu/compiler.h> /* For CAA_ARRAY_SIZE */
20#include "jhash.h" /* Example hash function */
21
22/*
23 * Nodes populated into the hash table.
24 */
25struct mynode {
26 int value; /* Node content */
27 int seqnum; /* Our node sequence number */
28 struct cds_lfht_node node; /* Chaining in hash table */
29 struct rcu_head rcu_head; /* For call_rcu() */
30};
31
32static
33int match(struct cds_lfht_node *ht_node, const void *_key)
34{
35 struct mynode *node =
36 caa_container_of(ht_node, struct mynode, node);
83e334d0 37 const int *key = _key;
34b3f359
MD
38
39 return *key == node->value;
40}
41
42static
43void free_node(struct rcu_head *head)
44{
45 struct mynode *node = caa_container_of(head, struct mynode, rcu_head);
46
47 free(node);
48}
49
70469b43 50int main(void)
34b3f359
MD
51{
52 int values[] = { -5, 42, 42, 36, 24, }; /* 42 is duplicated */
53 struct cds_lfht *ht; /* Hash table */
54 unsigned int i;
55 int ret = 0, seqnum = 0;
56 uint32_t seed;
57 struct cds_lfht_iter iter; /* For iteration on hash table */
58 struct cds_lfht_node *ht_node;
59 struct mynode *node;
60
61 /*
62 * Each thread need using RCU read-side need to be explicitly
63 * registered.
64 */
b9050d91 65 urcu_memb_register_thread();
34b3f359
MD
66
67 /* Use time as seed for hash table hashing. */
68 seed = (uint32_t) time(NULL);
69
70 /*
71 * Allocate hash table.
72 */
b9050d91 73 ht = cds_lfht_new_flavor(1, 1, 0,
34b3f359 74 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
b9050d91 75 &urcu_memb_flavor, NULL);
34b3f359
MD
76 if (!ht) {
77 printf("Error allocating hash table\n");
78 ret = -1;
79 goto end;
80 }
81
82 /*
83 * Add nodes to hash table.
84 */
85 for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
86 unsigned long hash;
87 int value;
88
89 node = malloc(sizeof(*node));
90 if (!node) {
91 ret = -1;
92 goto end;
93 }
94
95 cds_lfht_node_init(&node->node);
96 value = values[i];
97 node->value = value;
98 node->seqnum = seqnum++;
99 hash = jhash(&value, sizeof(value), seed);
100
101 /*
102 * cds_lfht_add() needs to be called from RCU read-side
103 * critical section.
104 */
b9050d91 105 urcu_memb_read_lock();
34b3f359
MD
106 ht_node = cds_lfht_add_replace(ht, hash, match, &value,
107 &node->node);
108 if (ht_node) {
109 struct mynode *ret_node =
110 caa_container_of(ht_node, struct mynode, node);
111
112 printf("Replaced node (key: %d, seqnum: %d) by (key: %d, seqnum: %d)\n",
113 ret_node->value, ret_node->seqnum,
114 node->value, node->seqnum);
b9050d91 115 urcu_memb_call_rcu(&ret_node->rcu_head, free_node);
34b3f359
MD
116 } else {
117 printf("Add (key: %d, seqnum: %d)\n",
118 node->value, node->seqnum);
119 }
b9050d91 120 urcu_memb_read_unlock();
34b3f359
MD
121 }
122
123 /*
124 * Iterate over each hash table node. Those will appear in
125 * random order, depending on the hash seed. Iteration needs to
126 * be performed within RCU read-side critical section.
127 */
128 printf("hash table content (random order):");
b9050d91 129 urcu_memb_read_lock();
34b3f359
MD
130 cds_lfht_for_each_entry(ht, &iter, node, node) {
131 printf(" (key: %d, seqnum: %d)",
132 node->value, node->seqnum);
133 }
b9050d91 134 urcu_memb_read_unlock();
34b3f359
MD
135 printf("\n");
136
137end:
b9050d91 138 urcu_memb_unregister_thread();
34b3f359
MD
139 return ret;
140}
This page took 0.04157 seconds and 4 git commands to generate.