Unsigned something whose width bigger than size_t's width

Viewed 62

I am writing a ring buffer using a linear array. Every element in array has an index. Writing index is always ahead of reading index and the 2 indexes use unsigned type as their underlying storage.The indexes constantly increase until wrapped. When wrapped occurs, the index will be added a additional number to keep the index % buffer size is the right buffer index. If a buffer size length data is written at the moment, wrapped will occur again. In this case, uint16_t instead of uint8_t is the right choice for the indexes underlying data type for uint8_t data range buffer. 2 uint16_t indexes works fine for uint8_t data range since one uint16_t minus another always return the right distance. But 2 uint8_t indexes cannot distinguish 0 and full case for uint8_t(same type). As the same reason, uint32_t works fine for uint16_t, uint64_t works fine for uint32_t, but nothing works for uint64_t(size_t) on my 64-bit computer. Actually, I only need one bit more than size_t's width - unsigned long long long type : 65; for example.

Is there a data structure or algorithm helps to get the distance between 2 indexes in above size_t case?

I finally figured out how to implement unsigned number structure type bigger than size_t. So it is not a problem now. Thanks everyone.

Some code:

#define UINT_TYPE_NX(w) uint##w##_t
#define UINT_TYPE(w) UINT_TYPE_NX(w)
#define UINT_TYPE_MAX_NX(w) UINT##w##_MAX
#define UINT_TYPE_MAX(w)    UINT_TYPE_MAX_NX(w)

#define S_TYPE      UINT_TYPE(S_TYPE_WIDTH)
#define S_TYPE_MAX      UINT_TYPE_MAX(S_TYPE_WIDTH)

#if S_TYPE_MAX == SIZE_MAX
#error S_TYPE_MAX cannot be SIZE_MAX(maximum value to size_t)
#endif

typedef struct  {
    volatile size_t w;  /* write position */
    volatile size_t r;      /* read position */
    S_TYPE  size;
    uint8_t buf[];
} ringbuf_t;

ringbuf_t* ringbuf_create(S_TYPE size);
void ringbuf_destroy(ringbuf_t *restrict*restrict rb_pointer);
bool ringbuf_write(const void *restrict buf, S_TYPE data_length, ringbuf_t *restrict rb);
bool __ringbuf_read_internal_called_only(void *restrict buf, S_TYPE length, ringbuf_t *restrict rb, S_TYPE start, bool remove);

static inline bool ringbuf_read(void *restrict buf, S_TYPE length, ringbuf_t *restrict rb) {
    if (!buf) {
        return false;
    }
    return __ringbuf_read_internal_called_only(buf, length, rb, 0, true);
}

static inline bool ringbuf_peek(void *restrict buf, S_TYPE length, ringbuf_t *restrict rb) {
    if (!buf) {
        return false;
    }
    return __ringbuf_read_internal_called_only(buf, length, rb, 0, false);
}

static inline bool ringbuf_pos_peek(void *restrict buf, S_TYPE length, ringbuf_t *restrict rb, S_TYPE begin) {
    if (!buf) {
        return false;
    }
    return __ringbuf_read_internal_called_only(buf, length, rb, begin, false);
}

static inline bool ringbuf_remove(S_TYPE length, ringbuf_t *restrict rb) {
    return __ringbuf_read_internal_called_only(NULL, length, rb, 0, true);
}
static inline S_TYPE ringbuf_supplyment(ringbuf_t *restrict rb) {
    S_TYPE ret = SIZE_MAX % rb->size;
    return ret + 1 == rb->size ? 0 : ret + 1;
}

static inline S_TYPE ringbuf_data_length_reader_calls_only(ringbuf_t *restrict rb) {
    size_t w = rb->w;
    return w - rb->r - (w < rb->r ? ringbuf_supplyment(rb) : 0);
}

static inline S_TYPE ringbuf_free_space_writer_calls_only(ringbuf_t *restrict rb) {
    size_t r = rb->r;
    return rb->size - (rb->w - r - (rb->w < r ? ringbuf_supplyment(rb) : 0));
}
0 Answers
Related