Skip to content

Instantly share code, notes, and snippets.

@wsd1
Last active February 26, 2024 02:16
Show Gist options
  • Save wsd1/b57ce4946720084549dd06254493827c to your computer and use it in GitHub Desktop.
Save wsd1/b57ce4946720084549dd06254493827c to your computer and use it in GitHub Desktop.
简单精炼的queue实现
/*
From https://github.com/JSchaenzle/c-message-queue
20240224: Add 2 APIs
20240226: shxt.Bugs. (p_queue->read_idx)++ & (capacity - 1) => (p_queue->read_idx)++ % capacity
*/
#ifndef QUEUE_H
#define QUEUE_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
enum enqueue_result {
ENQUEUE_RESULT_SUCCESS,
ENQUEUE_RESULT_FULL,
};
enum dequeue_result {
DEQUEUE_RESULT_SUCCESS,
DEQUEUE_RESULT_EMPTY,
};
#define ARRAY_LENGTH(A) (sizeof(A)/sizeof((A)[0]))
#define QUEUE_DECLARATION(NAME, ITEM_TYPE, NUM_ITEMS) \
struct NAME { \
uint16_t read_idx; \
uint16_t write_idx; \
ITEM_TYPE items[NUM_ITEMS]; \
}; \
void NAME ## _init(struct NAME * p_queue); \
enum enqueue_result NAME ##_enqueue(struct NAME * p_queue, ITEM_TYPE * p_new_item); \
enum dequeue_result NAME ##_dequeue(struct NAME * p_queue, ITEM_TYPE * p_item_out); \
enum enqueue_result NAME ##_enqueue_allc(struct NAME * p_queue, ITEM_TYPE * p_new_item);\
enum dequeue_result NAME ##_dequeue_ptr(struct NAME * p_queue, ITEM_TYPE * p_item_out); \
bool NAME ##_is_empty(struct NAME * p_queue);
#define QUEUE_DEFINITION(NAME, ITEM_TYPE) \
void NAME ## _init(struct NAME * p_queue) \
{ \
p_queue->read_idx = 0; \
p_queue->write_idx = 0; \
} \
\
enum enqueue_result NAME ##_enqueue(struct NAME * p_queue, ITEM_TYPE * p_new_item) { \
uint16_t elements_in = p_queue->write_idx - p_queue->read_idx; \
\
size_t const capacity = ARRAY_LENGTH(p_queue->items); \
if (elements_in == capacity) { \
return ENQUEUE_RESULT_FULL; \
} \
\
uint16_t i = (p_queue->write_idx)++ % capacity ; \
p_queue->items[i] = *p_new_item; \
return ENQUEUE_RESULT_SUCCESS; \
} \
\
enum dequeue_result NAME ##_dequeue(struct NAME * p_queue, ITEM_TYPE * p_item_out) { \
uint16_t elements_in = p_queue->write_idx - p_queue->read_idx; \
size_t const capacity = ARRAY_LENGTH(p_queue->items); \
\
if(elements_in == 0) { \
return DEQUEUE_RESULT_EMPTY; \
} \
\
uint16_t i = (p_queue->read_idx)++ % capacity ; \
*p_item_out = p_queue->items[i]; \
\
return DEQUEUE_RESULT_SUCCESS; \
} \
\
enum enqueue_result NAME ##_enqueue_alloc(struct NAME * p_queue, ITEM_TYPE ** p_item) {\
uint16_t elements_in = p_queue->write_idx - p_queue->read_idx; \
\
size_t const capacity = ARRAY_LENGTH(p_queue->items); \
if (elements_in == capacity) { \
return ENQUEUE_RESULT_FULL; \
} \
\
uint16_t i = (p_queue->write_idx)++ % capacity ; \
*p_item = &(p_queue->items[i]); \
return ENQUEUE_RESULT_SUCCESS; \
} \
\
enum dequeue_result NAME ##_dequeue_ptr(struct NAME * p_queue, ITEM_TYPE ** p_item_out){\
uint16_t elements_in = p_queue->write_idx - p_queue->read_idx; \
size_t const capacity = ARRAY_LENGTH(p_queue->items); \
\
if(elements_in == 0) { \
return DEQUEUE_RESULT_EMPTY; \
} \
\
uint16_t i = (p_queue->read_idx)++ % capacity ; \
*p_item_out = &(p_queue->items[i]); \
\
return DEQUEUE_RESULT_SUCCESS; \
} \
\
bool NAME ##_is_empty(struct NAME * p_queue) { \
return ((p_queue->write_idx - p_queue->read_idx) == 0); \
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment