Skip to content

Triple buffering primitive #67

@sbahra

Description

@sbahra

Taking epoch reclamation principles, SPSC use-case can be made efficient. @pkhuong dumped the following, which is a good starting point for the facility. This is a "concept" below from Paul.

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <ck_pr.h>

struct buffer_index {
    uint8_t byte;
};

/* We can obv. offset everything for 0 init, but let's keep things clear. */
#define BUFFER_INDEX_INIT = { 1 }

/* Not clear on the fencing; check ck_epoch... */
static inline size_t
buffer_index_read_index(const struct buffer_index *index)
{
    uint8_t byte = ck_pr_load_8(&index->byte);

    return byte >> 4;
}

static inline void
buffer_index_read_done(struct buffer_index *index)
{
    size_t next_read_index, read_index, write_index;
    uint8_t byte = ck_pr_load_8(&index->byte);

    read_index = byte >> 4;
    write_index = byte & 0xF;

    next_read_index = read_index + 1;
    if (next_read_index == 3) {
        next_read_index = 0;
    }

    if (next_read_index != write_index) {
        size_t prev_write_index = (write_index + 2) % 3;
        assert(prev_write_index == next_read_index);

        ck_pr_fence_load_store();
        ck_pr_store_8(&index->byte, (next_read_index << 4) | write_index);
    }

    return;
}

static inline size_t
buffer_index_write_index(const struct buffer_index *index)
{
    uint8_t byte = ck_pr_load_8(&index->byte);

    return byte & 0xF;
}

static inline size_t
buffer_index_write_start(struct buffer_index *index)
{
    size_t next_write_index, read_index, write_index;
    uint8_t byte = ck_pr_load_8(&index->byte);

    read_index = byte >> 4;
    write_index = byte & 0xF;

    next_write_index = write_index + 1;
    if (next_write_index == 3) {
        next_write_index = 0;
    }

    if (next_write_index == read_index) {
        return write_index;
    }

    assert(((read_index + 2) % 3) == next_write_index);
    ck_pr_store_8(&index->byte, (read_index << 4) | next_write_index);
    ck_pr_fence_store();
    return next_write_index;
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions