Created
October 29, 2013 06:32
-
-
Save ianmacartney/7209970 to your computer and use it in GitHub Desktop.
Basic dispatch queue for static memory applications (e.g. embedded). Caller is responsible for lifetime of all data passed in.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* q: queue of dispatches | |
* d: dispatch | |
* front/head = top of stack | |
* back/end/tail = bottom of stack | |
*/ | |
struct DQDispatch { | |
void (*fn)(void *); | |
void *param; | |
struct DQDispatch *next; | |
}; | |
struct DQueue { | |
struct DQDispatch *tail; | |
}; | |
struct DQDispatch *DQ_Head(struct DQueue *q); | |
void DQ_Push(struct DQueue *q, struct DQDispatch *d); | |
void DQ_Append(struct DQueue *q, struct DQDispatch *d); | |
struct DQDispatch *DQ_Pop(struct DQueue *q); | |
struct DQDispatch *DQ_PopAppend(struct DQueue *q); | |
struct DQDispatch *DQ_Next(struct DQueue *q, struct DQDispatch *d); | |
//.c | |
#include <stddef.h> | |
void DQ_Init(struct DQueue *q) { | |
q->tail = NULL; | |
} | |
struct DQDispatch *DQ_Head(struct DQueue *q) { | |
return q->tail? q->tail->next: NULL; | |
} | |
void DQ_Push(struct DQueue *q, struct DQDispatch *d) { | |
struct DQDispatch *tail = q->tail; | |
if (tail) { | |
d->next = tail->next; | |
tail->next = d; | |
} else { | |
d->next = d; | |
q->tail = d; | |
} | |
} | |
void DQ_Append(struct DQueue *q, struct DQDispatch *d) { | |
DQ_Push(q, d); | |
q->tail = q->tail->next; | |
} | |
struct DQDispatch *DQ_Pop(struct DQueue *q) { | |
struct DQDispatch *tail = q->tail; | |
struct DQDispatch *head = tail->next; | |
if (head == tail) { | |
q->tail = NULL; | |
} else { | |
tail->next = head->next; | |
} | |
head->next = NULL; | |
return head; | |
} | |
struct DQDispatch *DQ_Pop_append(struct DQueue *q) { | |
struct DQDispatch *tail = q->tail; | |
if (tail) { | |
q->tail = tail->next; | |
} | |
return q->tail; | |
} | |
struct DQDispatch *DQ_Next(struct DQueue *q, struct DQDispatch *d) { | |
return d == q->tail? NULL: d->next; | |
} | |
#define DQ_TEST | |
#ifdef DQ_TEST | |
#include <assert.h> | |
#include <stdio.h> | |
#define TEST_SIZE 15 | |
int main(int argc, void **argv) { | |
static struct DQueue qist; | |
static struct DQueue *q = &qist; | |
static struct DQDispatch na[TEST_SIZE]; | |
static int ia[TEST_SIZE]; | |
int i; | |
DQ_Init(q); | |
for (i = 0; i < TEST_SIZE; i++) { | |
ia[i] = i; | |
na[i].param = &ia[i]; | |
DQ_Push(q, &na[i]); | |
} | |
assert(DQ_Head(q)); | |
assert(i == TEST_SIZE); | |
struct DQDispatch *d; | |
for (d = DQ_Head(q); d; d = DQ_Next(q, d)) { | |
i--; | |
assert(*(int*)d->param == i); | |
} | |
printf("Countdown from %i to 0!\r\n", TEST_SIZE - 1); | |
while(DQ_Head(q) && (d = DQ_Pop(q))) { | |
printf("%5i!\r\n", *(int*)d->param); | |
} | |
assert(DQ_Head(q) == NULL); | |
assert(i == 0); | |
for (; i < TEST_SIZE; i++) { | |
DQ_Append(q, &na[i]); | |
} | |
printf("Count 0 up to %i!\r\n", TEST_SIZE - 1); | |
struct DQDispatch *head = DQ_Head(q); | |
for (i = 0; i < TEST_SIZE; i++) { | |
d = DQ_Pop_append(q); | |
printf("%5i!\r\n", *(int*)d->param); | |
assert(*(int*)d->param == i); | |
} | |
assert(head == DQ_Head(q)); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment