CK_RING_DEQUEUE_SPSC(3)

πŸ’– ck_ring_dequeue_spsc β€” dequeue pointer from bounded FIFO πŸ’–

okay bestie, welcome to the ck_ring_dequeue_spsc(3) page, straight outta the Concurrency Kit manual, and yes it lives in libck so you're gonna want -lck when you link. let's get into it 🫢


✨ NAME ✨

ck_ring_dequeue_spsc β€” dequeue a pointer from a bounded FIFO, no cap πŸ’…


πŸ“š LIBRARY πŸ“š

Concurrency Kit β€” link it with -lck and you're golden πŸŽ€


🌸 SYNOPSIS 🌸

#include <ck_ring.h>

bool
ck_ring_dequeue_spsc(ck_ring_t *ring, ck_ring_buffer_t *buffer,
    void *result);

πŸ¦‹ DESCRIPTION πŸ¦‹

so like, the ck_ring_dequeue_spsc(3) function pulls a pointer OUT of the bounded buffer that ring points to, and it does it FIFO style β€” first in, first out, the way the universe intended. that pointer gets stored in the thing that result points to. iconic.

the buffer that buffer points to has to be unique to ring, bestie, no sharing, and it must point to an array of ck_ring_buffer_t that's long enough β€” and "long enough" means according to the power-of-2 number of elements in the buffer. math is math. πŸ“

now here's the serve: the ring and the buffer being decoupled from each other? that's on purpose. it exists to handle use-cases involving multiple address spaces and DMA, among other things. very demure, very mindful, very flexible.

if you're on non-POSIX platforms or you just want strict compliance with C, then the recommendation is to pass a pointer of type void ** for result. noted. ✍️

and the safety tea: this function is safe to call without locking for one concurrent invocation of ck_ring_dequeue_spsc(3) and up to one concurrent ck_ring_enqueue_spsc(3) invocation. that's the SPSC deal β€” single producer, single consumer, and that's the whole vibe. also it provides wait-free progress guarantees, which is lowkey the slay of the century. πŸ”₯


🌈 EXAMPLE 🌈

#include <ck_ring.h>

/* This ring was previously initialized with ck_ring_init. */
ck_ring_t ring;

/* The ring was initialized for 1023 elements. */
ck_ring_buffer_t buffer[1024];

void
dequeue(void)
{
        void *result;

        /* Dequeue from ring until it is empty. */
        while (ck_ring_dequeue_spsc(&ring, &buffer, &result) == true) {
                /*
                 * Results contains the oldest pointer in ring
                 * since the dequeue operation returned true.
                 */
                operation(result);
        }

        /* An empty ring was encountered, leave. */
        return;
}

see how the while loop just keeps going until it gets false? that's the whole loop-until-empty moment. she's eating and leaving no crumbs πŸ“


⭐ RETURN VALUES ⭐

  • returns true if the buffer was non-empty πŸ’– and the result of the dequeue operation is stored in the value that result points to.
  • returns false if the buffer was empty, and ngl, in that case the value in result is undefined. like, do not read it. don't do it. πŸ’€

πŸ‘‘ SEE ALSO πŸ‘‘

more info, as always, at http://concurrencykit.org/ 🌐✨


fr fr, remember: buffer is ring's exclusive bestie, result gets the pointer, and empty means false with an undefined result. iykyk 🧚

and that's the page, angel πŸ’œ this was CK_RING_DEQUEUE_SPSC(3) from April 20, 2013 β€” mwah, go dequeue something iconic πŸŽ€βœ¨

πŸ“¦ where this page comes from