summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ring.c59
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
 		);
 	}
 }