ae2f_docs
c89atomic_deque.h
1/*
2A double-ended queue (deque). This implements "LĂȘ et al., Correct and Efficient Work-Stealing for Weak Memory Models (PPoPP 2013)".
3
4This is lock-free and thread-safe, but with rules. Pushing and popping to/from the tail can only be done by one thread (usually
5the thread that owns the deque). Stealing from the head can be done by any thread.
6
7The capacity of the deque must be a power of 2, and it cannot be resized. If this is not suitable you'll need to repurpose this
8code to suit your requirements, or use something else.
9
10Use c89atomic_deque_push_tail() to push to the tail, c89atomic_deque_take_tail() to pop from the tail, and c89atomic_deque_take_head()
11to steal from the head. You can initialize the deque with c89atomic_deque_init(), but it is not strictly necessary so long as you
12zero out the head and tail before using it.
13
14This code will do validation against the capacity of the deque, but will not validate function parameters. It's up to you to ensure
15valid pointers are passed to all function calls.
16
17I've designed this with the intentenion that it be amalgamated into other projects. You may need to adapt the code to suit your
18specific requirements. The data type of the deque is defined by `C89ATOMIC_DEQUE_T` which defaults to `void*`. As a result the
19`*_ptr` variants of atomic operations are used. If you want to use a non-pointer type, you'll need to adapt the code appropriately.
20*/
21#ifndef c89atomic_deque_h
22#define c89atomic_deque_h
23
24#include "../c89atomic.h"
25
26#ifndef C89ATOMIC_DEQUE_API
27#define C89ATOMIC_DEQUE_API
28#endif
29
30typedef enum
31{
32 C89ATOMIC_DEQUE_SUCCESS = 0,
33 C89ATOMIC_DEQUE_OUT_OF_MEMORY, /* Can be returned when pushing and the queue is full. */
34 C89ATOMIC_DEQUE_NO_DATA_AVAILABLE, /* Can be returned when the queue is empty during a take or steal. */
35 C89ATOMIC_DEQUE_CANCELLED /* Can be returned in the event of a data race when stealing. */
36} c89atomic_deque_result;
37
38/* Capacity must be power of 2.*/
39#ifndef C89ATOMIC_DEQUE_CAP
40#define C89ATOMIC_DEQUE_CAP 256
41#endif
42
43#ifndef C89ATOMIC_DEQUE_T
44#define C89ATOMIC_DEQUE_T void*
45#endif
46
47/* BEG c89atomic_deque.h */
48typedef struct c89atomic_deque
49{
50 c89atomic_uint32 head;
51 c89atomic_uint32 tail;
53} c89atomic_deque;
54
55C89ATOMIC_DEQUE_API void c89atomic_deque_init(c89atomic_deque* pDeque);
56C89ATOMIC_DEQUE_API c89atomic_deque_result c89atomic_deque_push_tail(c89atomic_deque* pDeque, C89ATOMIC_DEQUE_T value);
57C89ATOMIC_DEQUE_API c89atomic_deque_result c89atomic_deque_take_tail(c89atomic_deque* pDeque, C89ATOMIC_DEQUE_T* pValue);
58C89ATOMIC_DEQUE_API c89atomic_deque_result c89atomic_deque_take_head(c89atomic_deque* pDeque, C89ATOMIC_DEQUE_T* pValue); /* Steal an item with this. */
59/* END c89atomic_deque.h */
60
61#endif /* c89atomic_deque_h */
#define c89atomic_memory_order_release
Definition c89atomic.h:583
#define c89atomic_memory_order_seq_cst
Definition c89atomic.h:585
#define c89atomic_memory_order_acquire
Definition c89atomic.h:582
#define c89atomic_memory_order_relaxed
Definition c89atomic.h:580
#define C89ATOMIC_DEQUE_T
#define C89ATOMIC_DEQUE_CAP
#define C89ATOMIC_DEQUE_API