Skip to content

Triple buffering primitive #67

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;
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions