Table of Contents

Bespoke algorithm

A bespoke algorithm, in the lock-free programming context, is a custom CAS-based data structure or protocol designed for one specific use case, rather than reaching for a general-purpose structure like Treiber stack or Michael-Scott queue. The general-purpose structures are designed to support arbitrary interleavings of arbitrary operations; a bespoke design instead exploits the specific access pattern of one particular problem to do less work than a general structure would.

Why go bespoke at all

A general-purpose lock-free queue has to handle every possible mix of concurrent enqueues and dequeues correctly. If the actual use case is narrower, say, exactly one producer and one consumer, a lot of that generality is pure overhead. A single-producer single-consumer (SPSC) ring buffer, for instance, needs no CAS at all: with one writer and one reader, a plain atomic load/store on the head and tail indices is sufficient, since there's no possibility of two threads racing to update the same index.

// SPSC ring buffer: no CAS needed, only one thread ever writes each index
_Atomic size_t head = 0;   // only the producer writes this
_Atomic size_t tail = 0;   // only the consumer writes this
 
bool push(ring_t *r, void *item) {
    size_t h = atomic_load_explicit(&head, memory_order_relaxed);
    size_t next = (h + 1) % r->capacity;
    if (next == atomic_load_explicit(&tail, memory_order_acquire)) return false; // full
    r->buf[h] = item;
    atomic_store_explicit(&head, next, memory_order_release);
    return true;
}

The tradeoff

A bespoke algorithm trades generality for performance, and sometimes for simplicity too, the SPSC ring buffer above is both faster and easier to get right than a general MPMC queue, precisely because it assumes less. The risk is that the assumption baked into the design (exactly one producer, a fixed capacity, no need to support arbitrary access patterns) has to actually hold at every call site, forever. A structure correctly built to assume single-producer access silently breaks (data races, corrupted state) if a second producer is ever added later without anyone revisiting the assumption. This is the standard tradeoff in performance-critical Parallel computing code: general-purpose lock-free structures are the safe default, and a bespoke design is worth the risk only when the access pattern is well understood, unlikely to change, and the performance gain actually matters.