-
Notifications
You must be signed in to change notification settings - Fork 326
Open
Labels
Description
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;
}