Home | History | Annotate | Line # | Download | only in urcu
      1 // SPDX-FileCopyrightText: 2010-2012 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      2 // SPDX-FileCopyrightText: 2011-2012 Lai Jiangshan <laijs (at) cn.fujitsu.com>
      3 //
      4 // SPDX-License-Identifier: LGPL-2.1-or-later
      5 
      6 #ifndef _URCU_WFCQUEUE_H
      7 #define _URCU_WFCQUEUE_H
      8 
      9 /*
     10  * Userspace RCU library - Concurrent Queue with Wait-Free Enqueue/Blocking Dequeue
     11  */
     12 
     13 #include <pthread.h>
     14 #include <stdbool.h>
     15 #include <urcu/compiler.h>
     16 #include <urcu/arch.h>
     17 
     18 #ifdef __cplusplus
     19 extern "C" {
     20 #endif
     21 
     22 /*
     23  * Concurrent queue with wait-free enqueue/blocking dequeue.
     24  *
     25  * This queue has been designed and implemented collaboratively by
     26  * Mathieu Desnoyers and Lai Jiangshan. Inspired from
     27  * half-wait-free/half-blocking queue implementation done by Paul E.
     28  * McKenney.
     29  */
     30 
     31 #define CDS_WFCQ_WOULDBLOCK	((struct cds_wfcq_node *) -1UL)
     32 
     33 enum cds_wfcq_ret {
     34 	CDS_WFCQ_RET_WOULDBLOCK =	-1,
     35 	CDS_WFCQ_RET_DEST_EMPTY =	0,
     36 	CDS_WFCQ_RET_DEST_NON_EMPTY =	1,
     37 	CDS_WFCQ_RET_SRC_EMPTY = 	2,
     38 };
     39 
     40 enum cds_wfcq_state {
     41 	CDS_WFCQ_STATE_LAST =		(1U << 0),
     42 };
     43 
     44 struct cds_wfcq_node {
     45 	struct cds_wfcq_node *next;
     46 };
     47 
     48 /*
     49  * Do not put head and tail on the same cache-line if concurrent
     50  * enqueue/dequeue are expected from many CPUs. This eliminates
     51  * false-sharing between enqueue and dequeue.
     52  */
     53 struct __cds_wfcq_head {
     54 	struct cds_wfcq_node node;
     55 };
     56 
     57 struct cds_wfcq_head {
     58 	struct cds_wfcq_node node;
     59 	pthread_mutex_t lock;
     60 };
     61 
     62 /*
     63  * In C, the transparent union allows calling functions that work on both
     64  * struct cds_wfcq_head and struct __cds_wfcq_head on any of those two
     65  * types.
     66  *
     67  * In C++, implement static inline wrappers using function overloading
     68  * to obtain an API similar to C.
     69  *
     70  * Avoid complaints from clang++ not knowing the transparent union
     71  * attribute.
     72  */
     73 #if defined(__clang__)
     74 #pragma clang diagnostic push
     75 #pragma clang diagnostic ignored "-Wignored-attributes"
     76 #endif
     77 typedef union {
     78 	struct __cds_wfcq_head *_h;
     79 	struct cds_wfcq_head *h;
     80 } __attribute__((__transparent_union__)) cds_wfcq_head_ptr_t;
     81 
     82 typedef union {
     83 	const struct __cds_wfcq_head *_h;
     84 	const struct cds_wfcq_head *h;
     85 } __attribute__((__transparent_union__)) cds_wfcq_head_const_ptr_t;
     86 #if defined(__clang__)
     87 #pragma clang diagnostic pop
     88 #endif
     89 
     90 #ifndef __cplusplus
     91 /*
     92  * This static inline is only present for compatibility with C++. It is
     93  * effect-less in C.
     94  */
     95 static inline struct __cds_wfcq_head *__cds_wfcq_head_cast(struct __cds_wfcq_head *head)
     96 {
     97 	return head;
     98 }
     99 
    100 /*
    101  * This static inline is only present for compatibility with C++. It is
    102  * effect-less in C.
    103  */
    104 static inline struct cds_wfcq_head *cds_wfcq_head_cast(struct cds_wfcq_head *head)
    105 {
    106 	return head;
    107 }
    108 
    109 /*
    110  * This static inline is only present for compatibility with C++. It is
    111  * effect-less in C.
    112  */
    113 static inline const struct __cds_wfcq_head *__cds_wfcq_head_const_cast(const struct __cds_wfcq_head *head)
    114 {
    115 	return head;
    116 }
    117 
    118 /*
    119  * This static inline is only present for compatibility with C++. It is
    120  * effect-less in C.
    121  */
    122 static inline const struct cds_wfcq_head *cds_wfcq_head_const_cast(const struct cds_wfcq_head *head)
    123 {
    124 	return head;
    125 }
    126 
    127 #else /* #ifndef __cplusplus */
    128 
    129 /*
    130  * This static inline is used by internally in the static inline
    131  * implementation of the API.
    132  */
    133 static inline cds_wfcq_head_ptr_t __cds_wfcq_head_cast(struct __cds_wfcq_head *head)
    134 {
    135 	cds_wfcq_head_ptr_t ret = { ._h = head };
    136 	return ret;
    137 }
    138 
    139 /*
    140  * This static inline is used by internally in the static inline
    141  * implementation of the API.
    142  */
    143 static inline cds_wfcq_head_ptr_t cds_wfcq_head_cast(struct cds_wfcq_head *head)
    144 {
    145 	cds_wfcq_head_ptr_t ret = { .h = head };
    146 	return ret;
    147 }
    148 
    149 /*
    150  * This static inline is used by internally in the static inline
    151  * implementation of the API.
    152  */
    153 static inline cds_wfcq_head_const_ptr_t __cds_wfcq_head_const_cast(const struct __cds_wfcq_head *head)
    154 {
    155 	cds_wfcq_head_const_ptr_t ret = { ._h = head };
    156 	return ret;
    157 }
    158 
    159 /*
    160  * This static inline is used by internally in the static inline
    161  * implementation of the API.
    162  */
    163 static inline cds_wfcq_head_const_ptr_t cds_wfcq_head_const_cast(const struct cds_wfcq_head *head)
    164 {
    165 	cds_wfcq_head_const_ptr_t ret = { .h = head };
    166 	return ret;
    167 }
    168 
    169 #endif /* #else #ifndef __cplusplus */
    170 
    171 struct cds_wfcq_tail {
    172 	struct cds_wfcq_node *p;
    173 };
    174 
    175 #ifdef _LGPL_SOURCE
    176 
    177 #include <urcu/static/wfcqueue.h>
    178 
    179 #define cds_wfcq_node_init		_cds_wfcq_node_init
    180 #define cds_wfcq_init			_cds_wfcq_init
    181 #define __cds_wfcq_init			___cds_wfcq_init
    182 #define cds_wfcq_destroy		_cds_wfcq_destroy
    183 #define cds_wfcq_empty			_cds_wfcq_empty
    184 #define cds_wfcq_enqueue		_cds_wfcq_enqueue
    185 
    186 /* Dequeue locking */
    187 #define cds_wfcq_dequeue_lock		_cds_wfcq_dequeue_lock
    188 #define cds_wfcq_dequeue_unlock		_cds_wfcq_dequeue_unlock
    189 
    190 /* Locking performed within cds_wfcq calls. */
    191 #define cds_wfcq_dequeue_blocking	_cds_wfcq_dequeue_blocking
    192 #define cds_wfcq_dequeue_with_state_blocking	\
    193 					_cds_wfcq_dequeue_with_state_blocking
    194 #define cds_wfcq_splice_blocking	_cds_wfcq_splice_blocking
    195 #define cds_wfcq_first_blocking		_cds_wfcq_first_blocking
    196 #define cds_wfcq_next_blocking		_cds_wfcq_next_blocking
    197 
    198 /* Locking ensured by caller by holding cds_wfcq_dequeue_lock() */
    199 #define __cds_wfcq_dequeue_blocking	___cds_wfcq_dequeue_blocking
    200 #define __cds_wfcq_dequeue_with_state_blocking	\
    201 					___cds_wfcq_dequeue_with_state_blocking
    202 #define __cds_wfcq_splice_blocking	___cds_wfcq_splice_blocking
    203 #define __cds_wfcq_first_blocking	___cds_wfcq_first_blocking
    204 #define __cds_wfcq_next_blocking	___cds_wfcq_next_blocking
    205 
    206 /*
    207  * Locking ensured by caller by holding cds_wfcq_dequeue_lock().
    208  * Non-blocking: deque, first, next return CDS_WFCQ_WOULDBLOCK if they
    209  * need to block. splice returns nonzero if it needs to block.
    210  */
    211 #define __cds_wfcq_dequeue_nonblocking	___cds_wfcq_dequeue_nonblocking
    212 #define __cds_wfcq_dequeue_with_state_nonblocking	\
    213 				___cds_wfcq_dequeue_with_state_nonblocking
    214 #define __cds_wfcq_splice_nonblocking	___cds_wfcq_splice_nonblocking
    215 #define __cds_wfcq_first_nonblocking	___cds_wfcq_first_nonblocking
    216 #define __cds_wfcq_next_nonblocking	___cds_wfcq_next_nonblocking
    217 
    218 #else /* !_LGPL_SOURCE */
    219 
    220 /*
    221  * Mutual exclusion of cds_wfcq_* / __cds_wfcq_* API
    222  *
    223  * Synchronization table:
    224  *
    225  * External synchronization techniques described in the API below is
    226  * required between pairs marked with "X". No external synchronization
    227  * required between pairs marked with "-".
    228  *
    229  * Legend:
    230  * [1] cds_wfcq_enqueue
    231  * [2] __cds_wfcq_splice (destination queue)
    232  * [3] __cds_wfcq_dequeue
    233  * [4] __cds_wfcq_splice (source queue)
    234  * [5] __cds_wfcq_first
    235  * [6] __cds_wfcq_next
    236  *
    237  *     [1] [2] [3] [4] [5] [6]
    238  * [1]  -   -   -   -   -   -
    239  * [2]  -   -   -   -   -   -
    240  * [3]  -   -   X   X   X   X
    241  * [4]  -   -   X   -   X   X
    242  * [5]  -   -   X   X   -   -
    243  * [6]  -   -   X   X   -   -
    244  *
    245  * Mutual exclusion can be ensured by holding cds_wfcq_dequeue_lock().
    246  *
    247  * For convenience, cds_wfcq_dequeue_blocking() and
    248  * cds_wfcq_splice_blocking() hold the dequeue lock.
    249  *
    250  * Besides locking, mutual exclusion of dequeue, splice and iteration
    251  * can be ensured by performing all of those operations from a single
    252  * thread, without requiring any lock.
    253  */
    254 
    255 /*
    256  * cds_wfcq_node_init: initialize wait-free queue node.
    257  */
    258 extern void cds_wfcq_node_init(struct cds_wfcq_node *node);
    259 
    260 /*
    261  * cds_wfcq_init: initialize wait-free queue. Pair with
    262  * cds_wfcq_destroy().
    263  */
    264 extern void cds_wfcq_init(struct cds_wfcq_head *head,
    265 		struct cds_wfcq_tail *tail);
    266 
    267 /*
    268  * cds_wfcq_destroy: destroy wait-free queue. Pair with
    269  * cds_wfcq_init().
    270  */
    271 extern void cds_wfcq_destroy(struct cds_wfcq_head *head,
    272 		struct cds_wfcq_tail *tail);
    273 
    274 /*
    275  * __cds_wfcq_init: initialize wait-free queue (without lock). Don't
    276  * pair with any destroy function.
    277  */
    278 extern void __cds_wfcq_init(struct __cds_wfcq_head *head,
    279 		struct cds_wfcq_tail *tail);
    280 
    281 /*
    282  * cds_wfcq_empty: return whether wait-free queue is empty.
    283  *
    284  * No memory barrier is issued. No mutual exclusion is required.
    285  */
    286 extern bool cds_wfcq_empty(cds_wfcq_head_const_ptr_t head,
    287 		const struct cds_wfcq_tail *tail);
    288 
    289 /*
    290  * cds_wfcq_dequeue_lock: take the dequeue mutual exclusion lock.
    291  */
    292 extern void cds_wfcq_dequeue_lock(struct cds_wfcq_head *head,
    293 		struct cds_wfcq_tail *tail);
    294 
    295 /*
    296  * cds_wfcq_dequeue_unlock: release the dequeue mutual exclusion lock.
    297  */
    298 extern void cds_wfcq_dequeue_unlock(struct cds_wfcq_head *head,
    299 		struct cds_wfcq_tail *tail);
    300 
    301 /*
    302  * cds_wfcq_enqueue: enqueue a node into a wait-free queue.
    303  *
    304  * Issues a full memory barrier before enqueue. No mutual exclusion is
    305  * required.
    306  *
    307  * Returns false if the queue was empty prior to adding the node.
    308  * Returns true otherwise.
    309  */
    310 extern bool cds_wfcq_enqueue(cds_wfcq_head_ptr_t head,
    311 		struct cds_wfcq_tail *tail,
    312 		struct cds_wfcq_node *node);
    313 
    314 /*
    315  * cds_wfcq_dequeue_blocking: dequeue a node from a wait-free queue.
    316  *
    317  * Content written into the node before enqueue is guaranteed to be
    318  * consistent, but no other memory ordering is ensured.
    319  * It is valid to reuse and free a dequeued node immediately.
    320  * Mutual exclusion with cds_wfcq_dequeue_blocking and dequeue lock is
    321  * ensured.
    322  */
    323 extern struct cds_wfcq_node *cds_wfcq_dequeue_blocking(
    324 		struct cds_wfcq_head *head,
    325 		struct cds_wfcq_tail *tail);
    326 
    327 /*
    328  * cds_wfcq_dequeue_with_state_blocking: dequeue with state.
    329  *
    330  * Same as cds_wfcq_dequeue_blocking, but saves whether dequeueing the
    331  * last node of the queue into state (CDS_WFCQ_STATE_LAST).
    332  */
    333 extern struct cds_wfcq_node *cds_wfcq_dequeue_with_state_blocking(
    334 		struct cds_wfcq_head *head,
    335 		struct cds_wfcq_tail *tail,
    336 		int *state);
    337 
    338 /*
    339  * cds_wfcq_splice_blocking: enqueue all src_q nodes at the end of dest_q.
    340  *
    341  * Dequeue all nodes from src_q.
    342  * dest_q must be already initialized.
    343  * Content written into the node before enqueue is guaranteed to be
    344  * consistent, but no other memory ordering is ensured.
    345  * Mutual exclusion with cds_wfcq_dequeue_blocking and dequeue lock is
    346  * ensured.
    347  *
    348  * Returns enum cds_wfcq_ret which indicates the state of the src or
    349  * dest queue.
    350  */
    351 extern enum cds_wfcq_ret cds_wfcq_splice_blocking(
    352 		struct cds_wfcq_head *dest_q_head,
    353 		struct cds_wfcq_tail *dest_q_tail,
    354 		struct cds_wfcq_head *src_q_head,
    355 		struct cds_wfcq_tail *src_q_tail);
    356 
    357 /*
    358  * __cds_wfcq_dequeue_blocking: dequeue a node from a wait-free queue.
    359  *
    360  * Content written into the node before enqueue is guaranteed to be
    361  * consistent, but no other memory ordering is ensured.
    362  * It is valid to reuse and free a dequeued node immediately.
    363  * Dequeue/splice/iteration mutual exclusion should be ensured by the
    364  * caller.
    365  */
    366 extern struct cds_wfcq_node *__cds_wfcq_dequeue_blocking(
    367 		cds_wfcq_head_ptr_t head,
    368 		struct cds_wfcq_tail *tail);
    369 
    370 /*
    371  * __cds_wfcq_dequeue_with_state_blocking: dequeue with state.
    372  *
    373  * Same as __cds_wfcq_dequeue_blocking, but saves whether dequeueing the
    374  * last node of the queue into state (CDS_WFCQ_STATE_LAST).
    375  */
    376 extern struct cds_wfcq_node *__cds_wfcq_dequeue_with_state_blocking(
    377 		cds_wfcq_head_ptr_t head,
    378 		struct cds_wfcq_tail *tail,
    379 		int *state);
    380 
    381 /*
    382  * __cds_wfcq_dequeue_nonblocking: dequeue a node from a wait-free queue.
    383  *
    384  * Same as __cds_wfcq_dequeue_blocking, but returns CDS_WFCQ_WOULDBLOCK
    385  * if it needs to block.
    386  */
    387 extern struct cds_wfcq_node *__cds_wfcq_dequeue_nonblocking(
    388 		cds_wfcq_head_ptr_t head,
    389 		struct cds_wfcq_tail *tail);
    390 
    391 /*
    392  * __cds_wfcq_dequeue_with_state_blocking: dequeue with state.
    393  *
    394  * Same as __cds_wfcq_dequeue_nonblocking, but saves whether dequeueing
    395  * the last node of the queue into state (CDS_WFCQ_STATE_LAST).
    396  */
    397 extern struct cds_wfcq_node *__cds_wfcq_dequeue_with_state_nonblocking(
    398 		cds_wfcq_head_ptr_t head,
    399 		struct cds_wfcq_tail *tail,
    400 		int *state);
    401 
    402 /*
    403  * __cds_wfcq_splice_blocking: enqueue all src_q nodes at the end of dest_q.
    404  *
    405  * Dequeue all nodes from src_q.
    406  * dest_q must be already initialized.
    407  * Mutual exclusion for src_q should be ensured by the caller as
    408  * specified in the "Synchronisation table".
    409  * Returns enum cds_wfcq_ret which indicates the state of the src or
    410  * dest queue. Never returns CDS_WFCQ_RET_WOULDBLOCK.
    411  */
    412 extern enum cds_wfcq_ret __cds_wfcq_splice_blocking(
    413 		cds_wfcq_head_ptr_t dest_q_head,
    414 		struct cds_wfcq_tail *dest_q_tail,
    415 		cds_wfcq_head_ptr_t src_q_head,
    416 		struct cds_wfcq_tail *src_q_tail);
    417 
    418 /*
    419  * __cds_wfcq_splice_nonblocking: enqueue all src_q nodes at the end of dest_q.
    420  *
    421  * Same as __cds_wfcq_splice_blocking, but returns
    422  * CDS_WFCQ_RET_WOULDBLOCK if it needs to block.
    423  */
    424 extern enum cds_wfcq_ret __cds_wfcq_splice_nonblocking(
    425 		cds_wfcq_head_ptr_t dest_q_head,
    426 		struct cds_wfcq_tail *dest_q_tail,
    427 		cds_wfcq_head_ptr_t src_q_head,
    428 		struct cds_wfcq_tail *src_q_tail);
    429 
    430 /*
    431  * __cds_wfcq_first_blocking: get first node of a queue, without dequeuing.
    432  *
    433  * Content written into the node before enqueue is guaranteed to be
    434  * consistent, but no other memory ordering is ensured.
    435  * Dequeue/splice/iteration mutual exclusion should be ensured by the
    436  * caller.
    437  *
    438  * Used by for-like iteration macros:
    439  * __cds_wfcq_for_each_blocking()
    440  * __cds_wfcq_for_each_blocking_safe()
    441  *
    442  * Returns NULL if queue is empty, first node otherwise.
    443  */
    444 extern struct cds_wfcq_node *__cds_wfcq_first_blocking(
    445 		cds_wfcq_head_ptr_t head,
    446 		struct cds_wfcq_tail *tail);
    447 
    448 /*
    449  * __cds_wfcq_first_nonblocking: get first node of a queue, without dequeuing.
    450  *
    451  * Same as __cds_wfcq_first_blocking, but returns CDS_WFCQ_WOULDBLOCK if
    452  * it needs to block.
    453  */
    454 extern struct cds_wfcq_node *__cds_wfcq_first_nonblocking(
    455 		cds_wfcq_head_ptr_t head,
    456 		struct cds_wfcq_tail *tail);
    457 
    458 /*
    459  * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing.
    460  *
    461  * Content written into the node before enqueue is guaranteed to be
    462  * consistent, but no other memory ordering is ensured.
    463  * Dequeue/splice/iteration mutual exclusion should be ensured by the
    464  * caller.
    465  *
    466  * Used by for-like iteration macros:
    467  * __cds_wfcq_for_each_blocking()
    468  * __cds_wfcq_for_each_blocking_safe()
    469  *
    470  * Returns NULL if reached end of queue, non-NULL next queue node
    471  * otherwise.
    472  */
    473 extern struct cds_wfcq_node *__cds_wfcq_next_blocking(
    474 		cds_wfcq_head_ptr_t head,
    475 		struct cds_wfcq_tail *tail,
    476 		struct cds_wfcq_node *node);
    477 
    478 /*
    479  * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing.
    480  *
    481  * Same as __cds_wfcq_next_blocking, but returns CDS_WFCQ_WOULDBLOCK if
    482  * it needs to block.
    483  */
    484 extern struct cds_wfcq_node *__cds_wfcq_next_nonblocking(
    485 		cds_wfcq_head_ptr_t head,
    486 		struct cds_wfcq_tail *tail,
    487 		struct cds_wfcq_node *node);
    488 
    489 #endif /* !_LGPL_SOURCE */
    490 
    491 /*
    492  * __cds_wfcq_for_each_blocking: Iterate over all nodes in a queue,
    493  * without dequeuing them.
    494  * @head: head of the queue (struct cds_wfcq_head or __cds_wfcq_head pointer).
    495  * @tail: tail of the queue (struct cds_wfcq_tail pointer).
    496  * @node: iterator on the queue (struct cds_wfcq_node pointer).
    497  *
    498  * Content written into each node before enqueue is guaranteed to be
    499  * consistent, but no other memory ordering is ensured.
    500  * Dequeue/splice/iteration mutual exclusion should be ensured by the
    501  * caller.
    502  */
    503 #define __cds_wfcq_for_each_blocking(head, tail, node)		\
    504 	for (node = __cds_wfcq_first_blocking(head, tail);	\
    505 		node != NULL;					\
    506 		node = __cds_wfcq_next_blocking(head, tail, node))
    507 
    508 /*
    509  * __cds_wfcq_for_each_blocking_safe: Iterate over all nodes in a queue,
    510  * without dequeuing them. Safe against deletion.
    511  * @head: head of the queue (struct cds_wfcq_head or __cds_wfcq_head pointer).
    512  * @tail: tail of the queue (struct cds_wfcq_tail pointer).
    513  * @node: iterator on the queue (struct cds_wfcq_node pointer).
    514  * @n: struct cds_wfcq_node pointer holding the next pointer (used
    515  *     internally).
    516  *
    517  * Content written into each node before enqueue is guaranteed to be
    518  * consistent, but no other memory ordering is ensured.
    519  * Dequeue/splice/iteration mutual exclusion should be ensured by the
    520  * caller.
    521  */
    522 #define __cds_wfcq_for_each_blocking_safe(head, tail, node, n)		       \
    523 	for (node = __cds_wfcq_first_blocking(head, tail),		       \
    524 			n = (node ? __cds_wfcq_next_blocking(head, tail, node) : NULL); \
    525 		node != NULL;						       \
    526 		node = n, n = (node ? __cds_wfcq_next_blocking(head, tail, node) : NULL))
    527 
    528 #ifdef __cplusplus
    529 }
    530 
    531 /*
    532  * In C++, implement static inline wrappers using function overloading
    533  * to obtain an API similar to C.
    534  */
    535 
    536 static inline cds_wfcq_head_ptr_t cds_wfcq_head_cast_cpp(struct __cds_wfcq_head *head)
    537 {
    538 	cds_wfcq_head_ptr_t ret = { ._h = head };
    539 	return ret;
    540 }
    541 
    542 static inline cds_wfcq_head_ptr_t cds_wfcq_head_cast_cpp(struct cds_wfcq_head *head)
    543 {
    544 	cds_wfcq_head_ptr_t ret = { .h = head };
    545 	return ret;
    546 }
    547 
    548 static inline cds_wfcq_head_const_ptr_t cds_wfcq_head_const_cast_cpp(const struct __cds_wfcq_head *head)
    549 {
    550 	cds_wfcq_head_const_ptr_t ret = { ._h = head };
    551 	return ret;
    552 }
    553 
    554 static inline cds_wfcq_head_const_ptr_t cds_wfcq_head_const_cast_cpp(const struct cds_wfcq_head *head)
    555 {
    556 	cds_wfcq_head_const_ptr_t ret = { .h = head };
    557 	return ret;
    558 }
    559 
    560 template<typename T> static inline bool cds_wfcq_empty(T head,
    561 		const struct cds_wfcq_tail *tail)
    562 {
    563 	return cds_wfcq_empty(cds_wfcq_head_const_cast_cpp(head), tail);
    564 }
    565 
    566 template<typename T> static inline bool cds_wfcq_enqueue(T head,
    567 		struct cds_wfcq_tail *tail,
    568 		struct cds_wfcq_node *node)
    569 {
    570 	return cds_wfcq_enqueue(cds_wfcq_head_cast_cpp(head), tail, node);
    571 }
    572 
    573 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_dequeue_blocking(
    574 		T head, struct cds_wfcq_tail *tail)
    575 {
    576 	return __cds_wfcq_dequeue_blocking(cds_wfcq_head_cast_cpp(head), tail);
    577 }
    578 
    579 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_dequeue_with_state_blocking(
    580 		T head, struct cds_wfcq_tail *tail, int *state)
    581 {
    582 	return __cds_wfcq_dequeue_with_state_blocking(cds_wfcq_head_cast_cpp(head),
    583 			tail, state);
    584 }
    585 
    586 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_dequeue_nonblocking(
    587 		T head, struct cds_wfcq_tail *tail)
    588 {
    589 	return __cds_wfcq_dequeue_nonblocking(cds_wfcq_head_cast_cpp(head), tail);
    590 }
    591 
    592 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_dequeue_with_state_nonblocking(
    593 		T head, struct cds_wfcq_tail *tail, int *state)
    594 {
    595 	return __cds_wfcq_dequeue_with_state_nonblocking(cds_wfcq_head_cast_cpp(head),
    596 			tail, state);
    597 }
    598 
    599 template<typename T, typename U> static inline enum cds_wfcq_ret __cds_wfcq_splice_blocking(
    600 		T dest_q_head,
    601 		struct cds_wfcq_tail *dest_q_tail,
    602 		U src_q_head,
    603 		struct cds_wfcq_tail *src_q_tail)
    604 {
    605 	return __cds_wfcq_splice_blocking(cds_wfcq_head_cast_cpp(dest_q_head),
    606 			dest_q_tail,
    607 			cds_wfcq_head_cast_cpp(src_q_head),
    608 			src_q_tail);
    609 }
    610 
    611 template<typename T, typename U> static inline enum cds_wfcq_ret __cds_wfcq_splice_nonblocking(
    612 		T dest_q_head,
    613 		struct cds_wfcq_tail *dest_q_tail,
    614 		U *src_q_head,
    615 		struct cds_wfcq_tail *src_q_tail)
    616 {
    617 	return __cds_wfcq_splice_nonblocking(cds_wfcq_head_cast_cpp(dest_q_head),
    618 			dest_q_tail,
    619 			cds_wfcq_head_cast_cpp(src_q_head),
    620 			src_q_tail);
    621 }
    622 
    623 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_first_blocking(
    624 		T head, struct cds_wfcq_tail *tail)
    625 {
    626 	return __cds_wfcq_first_blocking(cds_wfcq_head_cast_cpp(head), tail);
    627 }
    628 
    629 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_first_nonblocking(
    630 		T head, struct cds_wfcq_tail *tail)
    631 {
    632 	return __cds_wfcq_first_nonblocking(cds_wfcq_head_cast_cpp(head), tail);
    633 }
    634 
    635 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_next_blocking(
    636 		T head,
    637 		struct cds_wfcq_tail *tail,
    638 		struct cds_wfcq_node *node)
    639 {
    640 	return __cds_wfcq_next_blocking(cds_wfcq_head_cast_cpp(head), tail, node);
    641 }
    642 
    643 template<typename T> static inline struct cds_wfcq_node *__cds_wfcq_next_nonblocking(
    644 		T head,
    645 		struct cds_wfcq_tail *tail,
    646 		struct cds_wfcq_node *node)
    647 {
    648 	return __cds_wfcq_next_nonblocking(cds_wfcq_head_cast_cpp(head), tail, node);
    649 }
    650 
    651 #endif
    652 
    653 #endif /* _URCU_WFCQUEUE_H */
    654