Zephyr API 3.6.99
Loading...
Searching...
No Matches

Single Producer Single Consumer (SPSC) Lockfree Queue API. More...

Files

file  spsc_lockfree.h
 A lock-free and type safe power of 2 fixed sized single producer single consumer (SPSC) queue using a ringbuffer and atomics to ensure coherency.
 

Macros

#define SPSC_INITIALIZER(sz, buf)
 Statically initialize an spsc.
 
#define SPSC_DECLARE(name, type)
 Declare an anonymous struct type for an spsc.
 
#define SPSC_DEFINE(name, type, sz)
 Define an spsc with a fixed size.
 
#define spsc_size(spsc)   ((spsc)->_spsc.mask + 1)
 Size of the SPSC queue.
 
#define spsc_reset(spsc)
 Initialize/reset a spsc such that its empty.
 
#define spsc_acquire(spsc)
 Acquire an element to produce from the SPSC.
 
#define spsc_produce(spsc)
 Produce one previously acquired element to the SPSC.
 
#define spsc_produce_all(spsc)
 Produce all previously acquired elements to the SPSC.
 
#define spsc_drop_all(spsc)
 Drop all previously acquired elements.
 
#define spsc_consume(spsc)
 Consume an element from the spsc.
 
#define spsc_release(spsc)
 Release a consumed element.
 
#define spsc_release_all(spsc)
 Release all consumed elements.
 
#define spsc_acquirable(spsc)    ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); })
 Count of acquirable in spsc.
 
#define spsc_consumable(spsc)   ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
 Count of consumables in spsc.
 
#define spsc_peek(spsc)
 Peek at the first available item in queue.
 
#define spsc_next(spsc, item)
 Peek at the next item in the queue from a given one.
 
#define spsc_prev(spsc, item)
 Get the previous item in the queue from a given one.
 

Detailed Description

Single Producer Single Consumer (SPSC) Lockfree Queue API.

Macro Definition Documentation

◆ spsc_acquirable

#define spsc_acquirable (   spsc)     ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); })

#include <zephyr/sys/spsc_lockfree.h>

Count of acquirable in spsc.

Parameters
spscSPSC to get item count for

◆ spsc_acquire

#define spsc_acquire (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_in(spsc) + (spsc)->_spsc.acquire; \
bool spsc_acq = (idx - z_spsc_out(spsc)) < spsc_size(spsc); \
if (spsc_acq) { \
(spsc)->_spsc.acquire += 1; \
} \
spsc_acq ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})
#define spsc_size(spsc)
Size of the SPSC queue.
Definition: spsc_lockfree.h:124

Acquire an element to produce from the SPSC.

Parameters
spscSPSC to acquire an element from for producing
Returns
A pointer to the acquired element or null if the spsc is full

◆ spsc_consumable

#define spsc_consumable (   spsc)    ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })

#include <zephyr/sys/spsc_lockfree.h>

Count of consumables in spsc.

Parameters
spscSPSC to get item count for

◆ spsc_consume

#define spsc_consume (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
bool has_consumable = (idx != z_spsc_in(spsc)); \
if (has_consumable) { \
(spsc)->_spsc.consume += 1; \
} \
has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})

Consume an element from the spsc.

Parameters
spscSpsc to consume from
Returns
Pointer to element or null if no consumable elements left

◆ SPSC_DECLARE

#define SPSC_DECLARE (   name,
  type 
)

#include <zephyr/sys/spsc_lockfree.h>

Value:
static struct spsc_##name { \
struct spsc _spsc; \
type * const buffer; \
}

Declare an anonymous struct type for an spsc.

Parameters
nameName of the spsc symbol to be provided
typeType stored in the spsc

◆ SPSC_DEFINE

#define SPSC_DEFINE (   name,
  type,
  sz 
)

#include <zephyr/sys/spsc_lockfree.h>

Value:
BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \
static type __spsc_buf_##name[sz]; \
SPSC_DECLARE(name, type) name = SPSC_INITIALIZER(sz, __spsc_buf_##name);
#define SPSC_INITIALIZER(sz, buf)
Statically initialize an spsc.
Definition: spsc_lockfree.h:82
#define IS_POWER_OF_TWO(x)
Check if a x is a power of two.
Definition: util_macro.h:77

Define an spsc with a fixed size.

Parameters
nameName of the spsc symbol to be provided
typeType stored in the spsc
szSize of the spsc, must be power of 2 (ex: 2, 4, 8)

◆ spsc_drop_all

#define spsc_drop_all (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
do { \
(spsc)->_spsc.acquire = 0; \
} while (false)

Drop all previously acquired elements.

This makes all previous acquired elements available to be acquired again

Parameters
spscSPSC to drop all previously acquired elements or do nothing

◆ SPSC_INITIALIZER

#define SPSC_INITIALIZER (   sz,
  buf 
)

#include <zephyr/sys/spsc_lockfree.h>

Value:
{ \
._spsc = \
{ \
.acquire = 0, \
.consume = 0, \
.in = ATOMIC_INIT(0), \
.out = ATOMIC_INIT(0), \
.mask = sz - 1, \
}, \
.buffer = buf, \
}
#define ATOMIC_INIT(i)
Initialize an atomic variable.
Definition: atomic.h:59

Statically initialize an spsc.

Parameters
szSize of the spsc, must be power of 2 (ex: 2, 4, 8)
bufBuffer pointer

◆ spsc_next

#define spsc_next (   spsc,
  item 
)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = ((item) - (spsc)->buffer); \
bool has_next = \
z_spsc_mask(spsc, (idx + 1)) != (z_spsc_mask(spsc, z_spsc_in(spsc))); \
has_next ? &((spsc)->buffer[z_spsc_mask((spsc), idx + 1)]) : NULL; \
})

Peek at the next item in the queue from a given one.

Parameters
spscSPSC to peek at
itemPointer to an item in the queue
Returns
Pointer to element or null if none left

◆ spsc_peek

#define spsc_peek (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
bool has_consumable = (idx != z_spsc_in(spsc)); \
has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})

Peek at the first available item in queue.

Parameters
spscSpsc to peek into
Returns
Pointer to element or null if no consumable elements left

◆ spsc_prev

#define spsc_prev (   spsc,
  item 
)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
bool has_prev = idx != z_spsc_mask(spsc, z_spsc_out(spsc)); \
has_prev ? &((spsc)->buffer[z_spsc_mask(spsc, idx - 1)]) : NULL; \
})

Get the previous item in the queue from a given one.

Parameters
spscSPSC to peek at
itemPointer to an item in the queue
Returns
Pointer to element or null if none left

◆ spsc_produce

#define spsc_produce (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.acquire > 0) { \
(spsc)->_spsc.acquire -= 1; \
atomic_add(&(spsc)->_spsc.in, 1); \
} \
})
atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
Atomic addition.

Produce one previously acquired element to the SPSC.

This makes one element available to the consumer immediately

Parameters
spscSPSC to produce the previously acquired element or do nothing

◆ spsc_produce_all

#define spsc_produce_all (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.acquire > 0) { \
unsigned long acquired = (spsc)->_spsc.acquire; \
(spsc)->_spsc.acquire = 0; \
atomic_add(&(spsc)->_spsc.in, acquired); \
} \
})

Produce all previously acquired elements to the SPSC.

This makes all previous acquired elements available to the consumer immediately

Parameters
spscSPSC to produce all previously acquired elements or do nothing

◆ spsc_release

#define spsc_release (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.consume > 0) { \
(spsc)->_spsc.consume -= 1; \
atomic_add(&(spsc)->_spsc.out, 1); \
} \
})

Release a consumed element.

Parameters
spscSPSC to release consumed element or do nothing

◆ spsc_release_all

#define spsc_release_all (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.consume > 0) { \
unsigned long consumed = (spsc)->_spsc.consume; \
(spsc)->_spsc.consume = 0; \
atomic_add(&(spsc)->_spsc.out, consumed); \
} \
})

Release all consumed elements.

Parameters
spscSPSC to release consumed elements or do nothing

◆ spsc_reset

#define spsc_reset (   spsc)

#include <zephyr/sys/spsc_lockfree.h>

Value:
({ \
(spsc)->_spsc.consume = 0; \
(spsc)->_spsc.acquire = 0; \
atomic_set(&(spsc)->_spsc.in, 0); \
atomic_set(&(spsc)->_spsc.out, 0); \
})

Initialize/reset a spsc such that its empty.

Note that this is not safe to do while being used in a producer/consumer situation with multiple calling contexts (isrs/threads).

Parameters
spscSPSC to initialize/reset

◆ spsc_size

#define spsc_size (   spsc)    ((spsc)->_spsc.mask + 1)

#include <zephyr/sys/spsc_lockfree.h>

Size of the SPSC queue.

Parameters
spscSPSC reference