Oh wai
authorAlexander Strange <astrange@ithinksw.com>
Sun, 9 Nov 2003 05:41:03 +0000 (05:41 +0000)
committerAlexander Strange <astrange@ithinksw.com>
Sun, 9 Nov 2003 05:41:03 +0000 (05:41 +0000)
queue.c [new file with mode: 0755]
queue.h [new file with mode: 0755]

diff --git a/queue.c b/queue.c
new file mode 100755 (executable)
index 0000000..c69061f
--- /dev/null
+++ b/queue.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright (C) 2003 and beyond by Alexander Strange
+ * and the Dawn Of Infinity developers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This license is contained in the file "COPYING",
+ * which is included with this source code; it is available online at
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/*
+ * $Id$
+ *
+ */
+#include <stdlib.h>
+#include "queue.h"
+
+queue*
+qinit(queue *q,size_t defaultsize)
+{
+       pthread_rwlock_init(&q->pmutex, NULL);
+       if (!defaultsize) defaultsize = 16;
+       q->data = (void **) calloc(defaultsize, sizeof(void *));
+       q->begin = q->end = 0;
+       q->allocated = defaultsize;
+       q->filled = 0;
+       return q;
+}
+
+void
+qdel(queue * q)
+{
+       pthread_rwlock_destroy(&q->pmutex);
+       free(q->data);
+}
+
+void           *
+qpop(queue * q)
+{
+if (q->filled == 0) return (void*)0xABCDEF00;
+       int err = pthread_rwlock_wrlock(&q->pmutex);
+       void           *v = q->data[q->begin++];
+       q->filled--;
+        if (q->filled == 0) {q->begin = q->end = 0;}
+        if (q->begin >= q->allocated) q->begin = 0;
+       if(err == 0)
+       {
+               err = pthread_rwlock_unlock(&q->pmutex);
+       }
+       return v;
+}
+
+void
+qpush(queue * q, void *p)
+{
+       int err = pthread_rwlock_wrlock(&q->pmutex);
+    if (q->allocated == q->filled) q->allocated = growarray(&q->data,q->allocated);
+       q->data[q->end++] = p;
+       q->filled++;
+        if (q->end >= q->allocated) q->end = 0;
+       if(err == 0)
+       {
+               err = pthread_rwlock_unlock(&q->pmutex);
+       }
+}
+
+void
+qperform(queue *q, qperformer p, void *pctx)
+{
+    if (q->end == q->begin) return; //no handling wrapped around status
+                                   //in fact no handling anything but we'll handle nonwrapped first
+    int err = pthread_rwlock_rdlock(&q->pmutex);
+    if (q->end > q->begin) {
+       int i = q->begin, c = q->end - q->begin;
+       do 
+       {
+           p(pctx,q->data[i++]);
+       } while (c--);
+    } else {
+       int i = q->begin, c = q->filled;
+       while (c--) {
+           p(pctx,q->data[i++]);
+       }
+       i = 0;
+       c = q->end;
+       do {
+           p(pctx,q->data[i++]);
+       } while (c--);
+    }
+    q->filled = q->begin = q->end = 0;
+    if (err = 0) pthread_rwlock_unlock(&q->pmutex);
+}
+
+/* XXX this should not be in here, but whatever */
+/*
+ * XXX there should also be a reverse shrinkarray for when the fill size hits
+ * a low-water-mark point. FreeBSD at least will free up memory if you
+ * realloc something smaller.
+ */
+size_t
+growarray(void ***datap, size_t oldsize)
+{
+       size_t          newsize = oldsize + 8, diff = 8;
+    void **data = *datap;
+       *datap = reallocf(data, sizeof(void *[newsize]));
+        while (diff--) {data[oldsize+diff] = (void*)0xDDDADEDC;}
+        return newsize;
+}
\ No newline at end of file
diff --git a/queue.h b/queue.h
new file mode 100755 (executable)
index 0000000..ff43e78
--- /dev/null
+++ b/queue.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (C) 2003 and beyond by Alexander Strange
+ * and the Dawn Of Infinity developers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This license is contained in the file "COPYING",
+ * which is included with this source code; it is available online at
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/*
+ * $Id$
+ *
+ */
+#pragma once only
+#ifndef _QUEUE_H
+#define _QUEUE_H
+#include <pthread.h>
+#include <sys/types.h>
+
+typedef struct queue {
+    void **data;
+    size_t begin;
+    size_t end;
+    size_t allocated;
+    size_t filled;
+    pthread_rwlock_t pmutex;
+} queue;
+
+typedef void    (*qperformer) (void *context, void *p);
+
+extern queue *qinit(queue *q,size_t defaultsize);
+extern void qdel(queue *q);
+extern void *qpop(queue *q);
+extern void qpush(queue *q, void *p);
+extern size_t growarray(void ***datap, size_t oldsize);
+extern void qperform(queue *q, qperformer p, void *pctx);
+#endif
\ No newline at end of file