vsync / stack / quack.h
Lockfree concurrent stack/queue (Treiber stack)
Groups: Linearizable, Lock-free
It’s a queue! It’s a stack! No, it’s a quack!
Quack is a concurrent stack that can be accessed as queue. It is also known as Treiber stack. The producers call quack_push() to add new elements to the stack. The consumers call quack_popall() to return a singled-linked list in LIFO order (as a stack). The caller can change the order to FIFO order by calling quack_reverse(). The caller is reposible for iterating over the elements of the list.
Example quack
typedef struct {
quack_node_t n; // embed quack_node in your data structure
int value;
} node_t;
quack_t stack;
node_t *mynode;
// to push into the stack
quack_push(&stack, &mynode->n);
// to pop from and iterate in FIFO order
quack_node_t *n = quack_reverse(quack_popall(&stack));
for (; n != NULL; n = n->next) {
node_t *nn = (node_t*) n;
// use node
}
Reference
Treiber, R.K., 1986. Systems programming: Coping with parallelism.
Macros
| Macro | Description |
|---|---|
| QUACK_INIT | Initializer of quack. |
Macro QUACK_INIT
QUACK_INIT()
Initializer of quack.
Functions
| Function | Description |
|---|---|
| quack_init | Initializes quack. |
| quack_push | Pushes node into the quack. |
| quack_is_empty | Checks if quack is empty. |
| quack_popall | Pops all elements from the quack in LIFO order. |
| quack_reverse | Reverse order of elements taken from the quack (from LIFO to FIFO or vice-versa). |
Function quack_init
static void quack_init(quack_t *s)
Initializes quack.
Parameters:
q: quack data structure
Function quack_push
static void quack_push(quack_t *q, quack_node_t *n)
Pushes node into the quack.
Parameters:
q: quack data structuren: node element
Function quack_is_empty
static vbool_t quack_is_empty(quack_t *const q)
Checks if quack is empty.
Parameters:
q: quack data structure
Returns: true if there is an element in quack, false otherwise.
Function quack_popall
static quack_node_t* quack_popall(quack_t *q)
Pops all elements from the quack in LIFO order.
The user is responsible for iterating over the elements (accessible with next pointer).
Parameters:
q: quack data structure
Returns: head of quack
Function quack_reverse
static quack_node_t* quack_reverse(quack_node_t *n)
Reverse order of elements taken from the quack (from LIFO to FIFO or vice-versa).
Parameters:
n: head or tail of quack
Returns: tail or head of quack