# Ifndef _ e71_queue_h __# define _ e71_queue_h __# include "common. h "/** queue * @ type the Data type of the structure of the queue * + mp_head pointing to the header node * + mpp_tail_next pointing to the successor node pointer of the End Node */# define E7_QUEUE (type) \ struct {\ type * mp_first; \ type ** mpp_last_next; \}/** queue initialization * @ p_queue queue */# define E7_QUEUE_INIT (p_queue) \ {\ NULL, \ & (p_queue)-> mp_first ), \}/** queue node * @ type data type of the structure of the queue * + mp_next pointing to the successor node * + mpp_prev_next pointing to the successor node pointer of the predecessor node */# define E7_QUEUE_NODE (type) \ struct {\ type * mp_next; \ type ** mpp_prev_next; \}/** queue node initialization * @ p_node node */# define E7_QUEUE_NODE_INIT (p_node) {\ NULL, \ & (p_node)-> mp_next ), \}/** insert node from the end * @ p_queue queue * @ p_new_elm new element * @ m_node new element queue node name */# define E7_QUEUE_INSERT_TAIL (p_queue, p_new_elm, m_node) \ do {\ (p_new_elm)-> m_node.mp_next = NULL; \ (p_new_elm)-> m_node.mpp_prev_next = (p_queue)-> mpp_last_next; \ * (p_queue)-> mpp_last_next) = (p_new_elm); \ (p_queue)-> mpp_last_next = & (p_new_elm)-> m_node.mp_next); \} while (0) /** delete node from the header * @ p_queue queue * @ p_result the pop-up header node * @ m_mode the name of the queue node in the new element */# define E7_QUEUE_DELETE_HEAD (p_queue, p_result, m_node) \ do {\ (p_result) = (p_queue)-> mp_first; \ if (NULL = (p_result)-> m_node.mp_next) {\ (p_queue)-> mp_first = NULL; \ (p_queue)-> mpp_last_next = & (p_queue)-> mp_first); \} else {\ (p_queue)-> mp_first = (p_queue)-> mp_first-> m_node.mp_next; \ (p_queue)-> mp_first-> m_node.mpp_prev_next = (\ & (p_result)-> m_node.mp_next) \); \} \ (p_result)-> m_node.mp_next = NULL; \ (p_result)-> m_node.mpp_prev_next = NULL; \} while (0) # endif/* _ e71_queue_h __*/
Ps: it is not thread-safe. If necessary, you can encapsulate another layer.
Although the above macro version has some generics, it has limited application scope and is only suitable for RAII-like scenarios.
Modified Version:
# Ifndef _ e71_queue_h __# DEFINE _ e71_queue_h __# include "Common. H "typedef struct e7_queue e7_queue_st; typedef struct e7_queue_node e7_queue_node_st; /** simple queue * @ type the Data Type of the structure of the queue * + mp_first pointing to the header node * + mpp_last_next pointing to the successor node pointer of the End Node */struct e7_queue {e7_queue_node_st * mp_first; e7_queue_node_st ** mpp_last_next;};/** queue initialization * @ p_queue queue */static inline void e7_queue_init (e7_queue_st * p_queue) {assert (null! = P_queue); p_queue-> mp_first = NULL; p_queue-> mpp_last_next = & (p_queue-> mp_first);} # define e7_queue_init (p_queue) \ {\ null, \ & (p_queue)-> mp_first ), \}/** queue node * @ type data type of the structure of the queue * + mp_next pointing to the successor node * + mpp_prev_next pointing to the successor node pointer of the predecessor node */struct e7_queue_node {e7_queue_node_st * mp_next; e7_queue_node_st ** mpp_prev_next;};/** queue node initialization * @ p_node node */static inline void e7_queue_node_init (e7_queue_node_st * P_node) {assert (null! = P_node); p_node-> mp_next = NULL; p_node-> mpp_prev_next = & (p_node-> mp_next);} # define e7_queue_node_init (p_node) \ {\ null, \ & (p_node)-> mp_next ), \}/** insert node from the end * @ p_queue queue * @ p_new_node new node * @ p_mutex lock */static inline void e7_queue_push (e7_queue_st * p_queue, limit * p_new_node, pthread_mutex_t * p_mutex) {assert (null! = P_queue); Assert (null! = P_new_node); Assert (null! = P_mutex); Aggregate (p_mutex); p_new_node-> mp_next = NULL; p_new_node-> mpp_prev_next = p_queue-> mpp_last_next; * (p_queue-> mpp_last_next) = p_new_node; p_queue-> mpp_last_next = & (p_new_node-> mp_next); pthread_mutex_unlock (p_mutex );} /** delete node from the header * @ p_queue queue * @ p_mutex mutex lock */static inline queue * e7_queue_pop (e7_queue_st * p_queue, pthread_mutex_t * p_mutex) {limit * p_res Ult = NULL; Assert (null! = P_queue); Assert (null! = P_mutex); If (null = p_queue-> mp_first) {/* empty queue */goto final;} pthread_mutex_lock (p_mutex); p_result = p_queue-> mp_first; if (null = p_queue-> mp_first-> mp_next) {/* only one element */e7_queue_init (p_queue );} else {p_queue-> mp_first = p_queue-> mp_first-> mp_next; p_queue-> mp_first-> mpp_prev_next = & (p_result-> mp_next );} p_result-> mp_next = NULL; p_result-> mpp_prev_next = NULL; pthread_mutex_unlock (p_mutex); Final: Return p_result;} # endif/* _ e71_queue_h __*/