diff options
-rw-r--r-- | ring.c | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/ring.c b/ring.c index 409fcd4..49fdd9b 100644 --- a/ring.c +++ b/ring.c @@ -29,70 +29,77 @@ static_assert(!(RingLen & (RingLen - 1)), "power of two RingLen"); static struct { char *lines[RingLen]; time_t times[RingLen]; - size_t write; } ring; +size_t producer; + void ringProduce(const char *line) { - size_t i = ring.write++ % RingLen; + size_t i = producer++ % RingLen; if (ring.lines[i]) free(ring.lines[i]); ring.times[i] = time(NULL); ring.lines[i] = strdup(line); if (!ring.lines[i]) err(EX_OSERR, "strdup"); } +struct Consumer { + char *name; + size_t pos; +}; + static struct { - char **names; - size_t *ptrs; + struct Consumer *ptr; size_t cap, len; -} read; +} consumers; size_t ringConsumer(const char *name) { - for (size_t i = 0; i < read.len; ++i) { - if (!strcmp(read.names[i], name)) return i; + for (size_t i = 0; i < consumers.len; ++i) { + if (!strcmp(consumers.ptr[i].name, name)) return i; } - if (read.len == read.cap) { - read.cap = (read.cap ? read.cap * 2 : 8); - read.names = realloc(read.names, sizeof(*read.names) * read.cap); - if (!read.names) err(EX_OSERR, "realloc"); - read.ptrs = realloc(read.ptrs, sizeof(*read.ptrs) * read.cap); - if (!read.ptrs) err(EX_OSERR, "realloc"); + if (consumers.len == consumers.cap) { + consumers.cap = (consumers.cap ? consumers.cap * 2 : 8); + // FIXME: Keep old pointer around for saving when exiting for error. + consumers.ptr = realloc( + consumers.ptr, sizeof(*consumers.ptr) * consumers.cap + ); + if (!consumers.ptr) err(EX_OSERR, "realloc"); } - read.names[read.len] = strdup(name); - if (!read.names[read.len]) err(EX_OSERR, "strdup"); - read.ptrs[read.len] = 0; - return read.len++; + struct Consumer *consumer = &consumers.ptr[consumers.len]; + consumer->pos = 0; + consumer->name = strdup(name); + if (!consumer->name) err(EX_OSERR, "strdup"); + return consumers.len++; } size_t ringDiff(size_t consumer) { - assert(consumer < read.len); - return ring.write - read.ptrs[consumer]; + assert(consumer < consumers.len); + return producer - consumers.ptr[consumer].pos; } const char *ringPeek(time_t *time, size_t consumer) { - assert(consumer < read.len); if (!ringDiff(consumer)) return NULL; if (ringDiff(consumer) > RingLen) { - read.ptrs[consumer] = ring.write - RingLen; + consumers.ptr[consumer].pos = producer - RingLen; } - size_t i = read.ptrs[consumer] % RingLen; + size_t i = consumers.ptr[consumer].pos % RingLen; if (time) *time = ring.times[i]; return ring.lines[i]; } const char *ringConsume(time_t *time, size_t consumer) { const char *line = ringPeek(time, consumer); - read.ptrs[consumer]++; + consumers.ptr[consumer].pos++; return line; } void ringInfo(void) { - fprintf(stderr, "producer: %zu\n", ring.write); - for (size_t i = 0; i < read.len; ++i) { + fprintf(stderr, "producer: %zu\n", producer); + for (size_t i = 0; i < consumers.len; ++i) { fprintf( stderr, "consumer %s: %zu (%zu)\n", - read.names[i], read.ptrs[i], ring.write - read.ptrs[i] + consumers.ptr[i].name, + consumers.ptr[i].pos, producer - consumers.ptr[i].pos ); } } |