summary refs log tree commit diff
path: root/ring.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-10-29 23:04:58 -0400
committerJune McEnroe <june@causal.agency>2019-10-29 23:04:58 -0400
commiteeac134e697f77d85ecbb8d6bd572a4b592433aa (patch)
tree611c18cdc27f146aa96ec3f5c652dd4fc0466ea2 /ring.c
parentDo not duplicate origin on nick change (diff)
downloadpounce-eeac134e697f77d85ecbb8d6bd572a4b592433aa.tar.gz
pounce-eeac134e697f77d85ecbb8d6bd572a4b592433aa.zip
Allocate ring buffer at runtime
Diffstat (limited to 'ring.c')
-rw-r--r--ring.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/ring.c b/ring.c
index 474a6e4..0fec6d0 100644
--- a/ring.c
+++ b/ring.c
@@ -23,18 +23,25 @@
 
 #include "bounce.h"
 
-enum { RingLen = 4096 };
-static_assert(!(RingLen & (RingLen - 1)), "power of two RingLen");
-
 static struct {
-	char *lines[RingLen];
-	time_t times[RingLen];
+	size_t len;
+	char **lines;
+	time_t *times;
 } ring;
 
+void ringAlloc(size_t len) {
+	if (len & (len - 1)) errx(EX_CONFIG, "ring length must be power of two");
+	ring.lines = calloc(len, sizeof(*ring.lines));
+	if (!ring.lines) err(EX_OSERR, "calloc");
+	ring.times = calloc(len, sizeof(*ring.times));
+	if (!ring.times) err(EX_OSERR, "calloc");
+	ring.len = len;
+}
+
 size_t producer;
 
 void ringProduce(const char *line) {
-	size_t i = producer++ % RingLen;
+	size_t i = producer++ & (ring.len - 1);
 	if (ring.lines[i]) free(ring.lines[i]);
 	ring.times[i] = time(NULL);
 	ring.lines[i] = strdup(line);
@@ -79,17 +86,18 @@ size_t ringDiff(size_t consumer) {
 
 const char *ringPeek(time_t *time, size_t consumer) {
 	if (!ringDiff(consumer)) return NULL;
-	if (ringDiff(consumer) > RingLen) {
-		consumers.ptr[consumer].pos = producer - RingLen;
+	if (ringDiff(consumer) > ring.len) {
+		consumers.ptr[consumer].pos = producer - ring.len;
 	}
-	size_t i = consumers.ptr[consumer].pos % RingLen;
+	size_t i = consumers.ptr[consumer].pos & (ring.len - 1);
 	if (time) *time = ring.times[i];
+	assert(ring.lines[i]);
 	return ring.lines[i];
 }
 
 const char *ringConsume(time_t *time, size_t consumer) {
 	const char *line = ringPeek(time, consumer);
-	consumers.ptr[consumer].pos++;
+	if (line) consumers.ptr[consumer].pos++;
 	return line;
 }
 
@@ -124,10 +132,10 @@ int ringSave(FILE *file) {
 		if (writeString(file, consumers.ptr[i].name)) return -1;
 		if (writeSize(file, consumers.ptr[i].pos)) return -1;
 	}
-	for (size_t i = 0; i < RingLen; ++i) {
+	for (size_t i = 0; i < ring.len; ++i) {
 		if (writeTime(file, ring.times[i])) return -1;
 	}
-	for (size_t i = 0; i < RingLen; ++i) {
+	for (size_t i = 0; i < ring.len; ++i) {
 		if (!ring.lines[i]) break;
 		if (writeString(file, ring.lines[i])) return -1;
 	}
@@ -169,10 +177,10 @@ void ringLoad(FILE *file) {
 		readSize(file, &consumers.ptr[consumer].pos);
 	}
 
-	for (size_t i = 0; i < RingLen; ++i) {
+	for (size_t i = 0; i < ring.len; ++i) {
 		readTime(file, &ring.times[i]);
 	}
-	for (size_t i = 0; i < RingLen; ++i) {
+	for (size_t i = 0; i < ring.len; ++i) {
 		readString(file, &buf, &cap);
 		if (feof(file)) break;
 		ring.lines[i] = strdup(buf);