In general, I'd love some comments on this basic queue using dynamic allocation. In particular, I want comments about whether this queue is good in embedded systems, for example say a a sensor network gateway, which has to queue up packets to be forwarded on say a UART.
I hear normally that mallocs are a bad idea for embedded, so what are the pitfalls in such a scenario?
One thing is, that malloc could return that it was unable to allocate the required memory. But what I thought was that if I did the calculation and I was reasonably certain that I definitely have MAX_QSIZE amount of memory available for the MAX_DATSIZE then realistically I shouldn't be able to see malloc fail. Is that a correct assumption?
I am rewriting the same code for a version with static array and no mallocs as well, so I'll try to analyze how both behave.
Thank you for your time.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#define MAX_QSIZE 100
#define MAX_DATSIZE 128
struct node{
void *data;
struct node *next;
};
typedef struct node node_t;
typedef struct queue_t {
node_t *head;
node_t *tail;
int size;
} queue_t;
queue_t *q_init(void)
{
queue_t *q = malloc(sizeof (*q));
q->size = 0;
q->head = q->tail = NULL;
}
int q_push(queue_t *q, const void *pdata, int bsize)
{
if (q == NULL)
return -1;
if (q->size == MAX_QSIZE)
return -2;
if (bsize > MAX_DATSIZE)
return -3;
node_t *new = malloc(sizeof (*new));
new->next = NULL;
new->data = malloc(bsize);
bzero(new->data, bsize);
memcpy(new->data, pdata, bsize);
if (q->size == 0) {
q->head = new;
} else {
q->tail->next = new;
}
q->tail = new;
q->size++;
return 0;
}
node_t *q_peek(queue_t *q)
{
return q->head;
}
void q_pop(queue_t *q)
{
if (q->size == 0)
return;
node_t *this = q->head;
q->head = this->next;
free(this);
q->size--;
if (q->size == 0)
q->tail = NULL;
}
void freeq(queue_t *q)
{
while (q->head != NULL) {
node_t *t = q->head;
q->head = t->next;
free(t);
}
free(q);
}
void printq(queue_t *q)
{
int i = 0;
for (node_t *h = q->head; h != NULL; h = h->next) {
printf("[%d] %s\n", i++, (char*)h->data);
}
}
int main()
{
char *test[] =
{
"January",
"February",
"Random"
};
int numtest = sizeof test / sizeof test[0];
queue_t *nameq = q_init();
for (int i = 0; i < numtest; i++) {
q_push(nameq, test[i], strlen(test[i]));
}
printq(nameq);
q_pop(nameq);
printq(nameq);
char *hname = (char*)(q_peek(nameq)->data);
printf("head name = %s\n", hname);
freeq(nameq);
return 0;
}