Home | History | Annotate | Line # | Download | only in rculfqueue
      1 // SPDX-FileCopyrightText: 2013 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      2 //
      3 // SPDX-License-Identifier: MIT
      4 
      5 /*
      6  * This example shows how to dequeue nodes from a RCU lock-free queue.
      7  * This queue requires using a RCU scheme.
      8  */
      9 
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 
     13 #include <urcu/urcu-memb.h>	/* RCU flavor */
     14 #include <urcu/rculfqueue.h>	/* RCU Lock-free queue */
     15 #include <urcu/compiler.h>	/* For CAA_ARRAY_SIZE */
     16 
     17 /*
     18  * Nodes populated into the queue.
     19  */
     20 struct mynode {
     21 	int value;			/* Node content */
     22 	struct cds_lfq_node_rcu node;	/* Chaining in queue */
     23 	struct rcu_head rcu_head;	/* For call_rcu() */
     24 };
     25 
     26 static
     27 void free_node(struct rcu_head *head)
     28 {
     29 	struct mynode *node =
     30 		caa_container_of(head, struct mynode, rcu_head);
     31 
     32 	free(node);
     33 }
     34 
     35 int main(void)
     36 {
     37 	int values[] = { -5, 42, 36, 24, };
     38 	struct cds_lfq_queue_rcu myqueue;	/* Queue */
     39 	unsigned int i;
     40 	int ret = 0;
     41 
     42 	/*
     43 	 * Each thread need using RCU read-side need to be explicitly
     44 	 * registered.
     45 	 */
     46 	urcu_memb_register_thread();
     47 
     48 	cds_lfq_init_rcu(&myqueue, urcu_memb_call_rcu);
     49 
     50 	/*
     51 	 * Enqueue nodes.
     52 	 */
     53 	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
     54 		struct mynode *node;
     55 
     56 		node = malloc(sizeof(*node));
     57 		if (!node) {
     58 			ret = -1;
     59 			goto end;
     60 		}
     61 
     62 		cds_lfq_node_init_rcu(&node->node);
     63 		node->value = values[i];
     64 		/*
     65 		 * Both enqueue and dequeue need to be called within RCU
     66 		 * read-side critical section.
     67 		 */
     68 		urcu_memb_read_lock();
     69 		cds_lfq_enqueue_rcu(&myqueue, &node->node);
     70 		urcu_memb_read_unlock();
     71 	}
     72 
     73 	/*
     74 	 * Dequeue each node from the queue. Those will be dequeued from
     75 	 * the oldest (first enqueued) to the newest (last enqueued).
     76 	 */
     77 	printf("dequeued content:");
     78 	for (;;) {
     79 		struct cds_lfq_node_rcu *qnode;
     80 		struct mynode *node;
     81 
     82 		/*
     83 		 * Both enqueue and dequeue need to be called within RCU
     84 		 * read-side critical section.
     85 		 */
     86 		urcu_memb_read_lock();
     87 		qnode = cds_lfq_dequeue_rcu(&myqueue);
     88 		urcu_memb_read_unlock();
     89 		if (!qnode) {
     90 			break;	/* Queue is empty. */
     91 		}
     92 		/* Getting the container structure from the node */
     93 		node = caa_container_of(qnode, struct mynode, node);
     94 		printf(" %d", node->value);
     95 		urcu_memb_call_rcu(&node->rcu_head, free_node);
     96 	}
     97 	printf("\n");
     98 	/*
     99 	 * Release memory used by the queue.
    100 	 */
    101 	ret = cds_lfq_destroy_rcu(&myqueue);
    102 	if (ret) {
    103 		printf("Error destroying queue (non-empty)\n");
    104 	}
    105 end:
    106 	urcu_memb_unregister_thread();
    107 	return ret;
    108 }
    109