---
# System prepended metadata

title: 說碼解扣- QUEUE

---

## 說碼解扣-- QUEUE
### 1. 內容
- 簡介
    - 可以把佇列想像成有分出入口的選舉投票室，投票者必須遵守「從入口進入」與「從出口離開」的動線，先進入投票者會先完成投票離開，將此對應到佇列結構，其入口為佇列的尾端，出口為佇列的前端，投票者則為資料。
- 特色
    - 先進先出（First In First Out，FIFO）
    - 線性結構
    - 頭、尾端有索引值(front,rear)
- 功能
    - Enqueue(data)：從佇列尾端存入資料
    - Dequeue()：從佇列前端移除資料
    - getFirst()：回傳佇列前端(第一筆)的資料
    - getLast()：回傳佇列尾端(最後一筆)的資料
    - getSize()：回傳佇列目前的大小
    - isEmpty()：檢查佇列是否為空
- 應用
    - CPU的工作排程
    - 印表機的工作排序
    - 網路伺服器傳輸
### 2. 程式碼解說
:::spoiler queue_internal.h
```c==
#ifndef __QUEUE_INTERNAL_H__
#define __QUEUE_INTERNAL_H__
#include <stdio.h>
#include <stdlib.h>
#include <queue.h>

int8_t queue_lock_internal(queue_t *q);
int8_t queue_unlock_internal(queue_t *q);
int8_t queue_put_internal(queue_t *q, void *el, int (*action)(pthread_cond_t *, pthread_mutex_t *));
int8_t queue_get_internal(queue_t *q, void **e, int (*action)(pthread_cond_t *, pthread_mutex_t *), int (*cmp)(void *, void *), void *cmpel);
int8_t queue_destroy_internal(queue_t *q, uint8_t fd, void (*ff)(void *));
ction to release the memory, NULL => free()
int8_t queue_flush_internal(queue_t *q, uint8_t fd, void (*ff)(void *));
#endif /* __QUEUE_INTERNAL_H__ */

```
:::
:::spoiler queue.h
```c==
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> /* (u)intX_t */
#ifndef _WIN32
#include <unistd.h> /* usleep */
#else
#include <windows.h> /* Sleep */
#endif
#include <errno.h> /* EBUSY */

#include <pthread.h> /* pthread_mutex_t, pthread_cond_t */

#ifdef _WIN32
#define sleepmilli(x) Sleep(x)
#else
#define sleepmilli(x) usleep(x * 1000)
#endif

#ifndef UINTX_MAX
  typedef uint16_t uintX_t;
  #define UINTX_MAX UINT16_MAX
#endif

#define DEFINE_Q_DESTROY(fname, type) int8_t fname(queue_t *q, void (*ff)(type *)) { return queue_destroy_complete(q, (void (*)(void *))ff); }
#define DEFINE_Q_FLUSH(fname, type) int8_t fname(queue_t *q, void (*ff)(type *)) { return queue_flush_complete(q, (void (*)(void *))ff); }
#define DEFINE_Q_GET(fname, type) int8_t fname(queue_t *q, type **e) { return queue_get(q, (void **)e); }
#define DEFINE_Q_GET_WAIT(fname, type) int8_t fname(queue_t *q, type **e) { return queue_get_wait(q, (void **)e); }
#define DEFINE_Q_PUT(fname, type) int8_t fname(queue_t *q, type *e) { return queue_put(q, (void *)e); }
#define DEFINE_Q_PUT_WAIT(fname, type) int8_t fname(queue_t *q, type *e) { return queue_put_wait(q, (void *)e); }
#define DEFINE_Q_FLUSH_PUT(fname, type) int8_t fname(queue_t *q, void (*ff)(type *), type *e) { return queue_flush_complete_put(q, (void (*)(void *))ff, (void *)e); }

typedef enum queue_erros_e {
	Q_OK = 0,
	Q_ERR_INVALID = -1,
	Q_ERR_LOCK = -2,
	Q_ERR_MEM = -3,
	Q_ERR_NONEWDATA = -4,
	Q_ERR_INVALID_ELEMENT = -5,
	Q_ERR_INVALID_CB = -6,
	Q_ERR_NUM_ELEMENTS = -7
} queue_errors_t;

typedef struct queue_element_s {
	void *data;
	struct queue_element_s *next;
} queue_element_t;

typedef struct queue_s {
	queue_element_t *first_el, *last_el;
	// (max.) number of elements
	uintX_t num_els;
	uintX_t max_els;
	// no new data allowed
	uint8_t new_data;
	// sorted queue
	int8_t sort;
	int8_t asc_order;
	int (*cmp_el)(void *, void *);
	// multithreaded
	pthread_mutex_t *mutex;
	pthread_cond_t *cond_get;
	pthread_cond_t *cond_put;
} queue_t;

/**
  * initializes and allocates a queue with unlimited elements
  *
  * returns NULL on error, or a pointer to the queue
  */
queue_t *queue_create(void);

queue_t *queue_create_limited(uintX_t max_elements);

queue_t *queue_create_sorted(int8_t asc, int (*cmp)(void *, void *));

queue_t *queue_create_limited_sorted(uintX_t max_elements, int8_t asc, int (*cmp)(void *, void *));

int8_t queue_destroy(queue_t *q);

int8_t queue_destroy_complete(queue_t *q, void (*ff)(void *));

int8_t queue_flush(queue_t *q);

int8_t queue_flush_complete(queue_t *q, void (*ff)(void *));

int8_t queue_flush_put(queue_t *q, void (*ff)(void *), void *e);

int8_t queue_flush_complete_put(queue_t *q, void (*ff)(void *), void *e);

uintX_t queue_elements(queue_t *q);

int8_t queue_empty(queue_t *q);

int8_t queue_put(queue_t *q, void *e);

int8_t queue_put_wait(queue_t *q, void *e);

int8_t queue_get(queue_t *q, void **e);

int8_t queue_get_wait(queue_t *q, void **e);

int8_t queue_get_filtered(queue_t *q, void **e, int (*cmp)(void *, void *), void *cmpel);

int8_t queue_set_new_data(queue_t *q, uint8_t v);

uint8_t queue_get_new_data(queue_t *q);

#endif /* __QUEUE_H__ */

```
:::

:::spoiler queue.c

   ```c
    #include "queue.h"
    #include "queue_internal.h"

    queue_t *queue_create(void) {
        queue_t *q = (queue_t *)malloc(sizeof(queue_t));
        if(q != NULL) {
            q->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
            if(q->mutex == NULL) {
                free(q);
                return NULL;
            }
            pthread_mutex_init(q->mutex, NULL);

            q->cond_get = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));
            if(q->cond_get == NULL) {
                pthread_mutex_destroy(q->mutex);
                free(q->mutex);
                free(q);
                return NULL;
            }
            pthread_cond_init(q->cond_get, NULL);

            q->cond_put = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));
            if(q->cond_put == NULL) {
                pthread_cond_destroy(q->cond_get);
                free(q->cond_get);
                pthread_mutex_destroy(q->mutex);
                free(q->mutex);
                free(q);
                return NULL;
            }
            pthread_cond_init(q->cond_put, NULL);

            q->first_el = NULL;
            q->last_el = NULL;
            q->num_els = 0;
            q->max_els = 0;
            q->new_data = 1;
            q->sort = 0;
            q->asc_order = 1;
            q->cmp_el = NULL;
        }

        return q;
    }

    queue_t *queue_create_limited(uintX_t max_elements) {
        queue_t *q = queue_create();
        if(q != NULL)
            q->max_els = max_elements;

        return q;
    }

    queue_t *queue_create_sorted(int8_t asc, int (*cmp)(void *, void *)) {
        if(cmp == NULL)
            return NULL;

        queue_t *q = queue_create();
        if(q != NULL) {
            q->sort = 1;
            q->asc_order = asc;
            q->cmp_el = cmp;
        }

        return q;
    }

    queue_t *queue_create_limited_sorted(uintX_t max_elements, int8_t asc, int (*cmp)(void *, void *)) {
        if(cmp == NULL)
            return NULL;

        queue_t *q = queue_create();
        if(q != NULL) {
            q->max_els = max_elements;
            q->sort = 1;
            q->asc_order = asc;
            q->cmp_el = cmp;
        }

        return q;
    }

    int8_t queue_destroy(queue_t *q) {
        if(q == NULL)
            return Q_ERR_INVALID;
        return queue_destroy_internal(q, 0, NULL);
    }

    int8_t queue_destroy_complete(queue_t *q, void (*ff)(void *)) {
        if(q == NULL)
            return Q_ERR_INVALID;
        return queue_destroy_internal(q, 1, ff);
    }

    int8_t queue_flush(queue_t *q) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_flush_internal(q, 0, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
        }

    int8_t queue_flush_complete(queue_t *q, void (*ff)(void *)) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_flush_internal(q, 1, ff);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    uintX_t queue_elements(queue_t *q) {
        uintX_t ret = UINTX_MAX;
        if(q == NULL)
            return ret;
        if (0 != queue_lock_internal(q))
            return ret;

        ret = q->num_els;

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return ret;
    }

    int8_t queue_empty(queue_t *q) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        uint8_t ret;
        if(q->first_el == NULL || q->last_el == NULL)
            ret = 1;
        else
            ret = 0;

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return ret;
    }

    int8_t queue_set_new_data(queue_t *q, uint8_t v) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;
        q->new_data = v;
        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;

        if(q->new_data == 0) {
            // notify waiting threads, when new data isn't accepted
            pthread_cond_broadcast(q->cond_get);
            pthread_cond_broadcast(q->cond_put);
        }

        return Q_OK;
    }

    uint8_t queue_get_new_data(queue_t *q) {
        if(q == NULL)
            return 0;
        if (0 != queue_lock_internal(q))
            return 0;

        uint8_t r = q->new_data;

        if (0 != queue_unlock_internal(q))
            return 0;
        return r;
    }

    int8_t queue_put(queue_t *q, void *el) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_put_internal(q, el, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_put_wait(queue_t *q, void *el) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_put_internal(q, el, pthread_cond_wait);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_get(queue_t *q, void **e) {
        *e = NULL;
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_get_internal(q, e, NULL, NULL, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_get_wait(queue_t *q, void **e) {
        *e = NULL;
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_get_internal(q, e, pthread_cond_wait, NULL, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_get_filtered(queue_t *q, void **e, int (*cmp)(void *, void *), void *cmpel) {
        *e = NULL;
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_get_internal(q, e, NULL, cmp, cmpel);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_flush_put(queue_t *q, void (*ff)(void *), void *e) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_flush_internal(q, 0, NULL);
        r = queue_put_internal(q, e, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }

    int8_t queue_flush_complete_put(queue_t *q, void (*ff)(void *), void *e) {
        if(q == NULL)
            return Q_ERR_INVALID;
        if (0 != queue_lock_internal(q))
            return Q_ERR_LOCK;

        int8_t r = queue_flush_internal(q, 1, ff);
        r = queue_put_internal(q, e, NULL);

        if (0 != queue_unlock_internal(q))
            return Q_ERR_LOCK;
        return r;
    }
   ```
:::
1. `queue_create`:
   - 為新的`queue_t`結構分配內存。
   - 初始化用於同步的互斥鎖和條件變量。
   - 設置queue結構的其他成員的初始值。
   - 返回指向創建的queue的指針。

2. `queue_create_limited`:
   - 調用`queue_create`以創建新的queue。
   - 設置queue的最大元素數（`max_elements`）。
   - 返回指向創建的queue的指針。

3. `queue_create_sorted`:
   - 調用`queue_create`以創建新的隊列。
   - 啟用排序，設置`sort`標誌。
   - 設置排序順序（升序或降序）和比較函數。
   - 返回指向創建的queue的指針。

4. `queue_create_limited_sorted`:
   - 調用`queue_create`以創建新的隊列。
   - 設置最大元素數，啟用指定順序和比較函數的排序。
   - 返回指向創建的隊列的指針。

5. `queue_destroy`:
   - 摧毀queue及其相關的資源，不釋放存儲的元素。
   - 如果queue無效，則返回錯誤碼。

6. `queue_destroy_complete`:
   - 摧毀queue，其相關的資源，並可選擇為每個存儲的元素調用清理函數。
   - 如果queue無效，則返回錯誤碼。

7. `queue_flush`:
   - 從queue中移除所有元素，但不釋放它們。
   - 如果queue無效或存在鎖定問題，則返回錯誤碼。

8. `queue_flush_complete`:
   - 從queue中移除所有元素，可選擇為每個元素調用清理函數。
   - 如果queue無效或存在鎖定問題，則返回錯誤碼。

9. `queue_elements`:
   - 返回queue中當前元素的數量。
   - 如果queue無效或存在鎖定問題，則返回`UINTX_MAX`。

10. `queue_empty`:
       - 檢查queue是否為空。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

11. `queue_set_new_data`:
       - 設置queue中的`new_data`標誌。
       - 如果不接受新數據，則通知等待的線程。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

12. `queue_get_new_data`:
       - 返回queue中`new_data`標誌的值。
       - 如果queue無效或存在鎖定問題，則返回0。

13. `queue_put`:
       - 向queue添加元素。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

14. `queue_put_wait`:
       - 向queue添加元素，如果隊列已滿，則等待。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

15. `queue_get`:
       - 從queue列中檢索元素。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

16. `queue_get_wait`:
       - 從queue中檢索元素，如果隊列為空，則等待。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

17. `queue_get_filtered`:
       - 根據過濾條件從queue中檢索元素。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

18. `queue_flush_put`:
       - 從queue中移除所有元素並添加新元素。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

19. `queue_flush_complete_put`:
       - 從queue中移除所有元素，為每個元素調用清理函數，然後添加新元素。
       - 如果queue無效或存在鎖定問題，則返回錯誤碼。

:::spoiler queue_internal.c

```c
#include "queue.h"
#include "queue_internal.h"

int8_t queue_lock_internal(queue_t *q) {
	if (q == NULL)
		return Q_ERR_INVALID;
	if(0 != pthread_mutex_lock(q->mutex))
		return Q_ERR_LOCK;
	return Q_OK;
}

int8_t queue_unlock_internal(queue_t *q) {
	if (q == NULL)
		return Q_ERR_INVALID;
	if(0 != pthread_mutex_unlock(q->mutex))
		return Q_ERR_LOCK;
	return Q_OK;
}

int8_t queue_destroy_internal(queue_t *q, uint8_t fd, void (*ff)(void *)) {
	int error = Q_OK;

	error = queue_set_new_data(q, 0);
	error = queue_lock_internal(q);
	
	error = queue_flush_internal(q, fd, ff);
	
	error = pthread_cond_destroy(q->cond_get);
	free(q->cond_get);
	error = pthread_cond_destroy(q->cond_put);
	free(q->cond_put);
	
	error = queue_unlock_internal(q);
	while(EBUSY == (error = pthread_mutex_destroy(q->mutex)))
		sleepmilli(100);
	free(q->mutex);
	
	free(q);
	return error;
}

int8_t queue_flush_internal(queue_t *q, uint8_t fd, void (*ff)(void *)) {
	if(q == NULL)
		return Q_ERR_INVALID;
	
	queue_element_t *qe = q->first_el;
	queue_element_t *nqe = NULL;
	while(qe != NULL) {
		nqe = qe->next;
		if(fd != 0 && ff == NULL) {
			free(qe->data);
		} else if(fd != 0 && ff != NULL) {
			ff(qe->data);
		}
		free(qe);
		qe = nqe;
	}
	q->first_el = NULL;
	q->last_el = NULL;
	q->num_els = 0;
	
	return Q_OK;
}

int8_t queue_put_internal(queue_t *q , void *el, int (*action)(pthread_cond_t *, pthread_mutex_t *)) {
	if(q == NULL) 
		return Q_ERR_INVALID;
		
	if(q->new_data == 0) { 
		return Q_ERR_NONEWDATA;
	}
	
	if(q->num_els == (UINTX_MAX - 1) || (q->max_els != 0 && q->num_els == q->max_els)) {
		if(action == NULL) {
			return Q_ERR_NUM_ELEMENTS;
		} else {
			while ((q->num_els == (UINTX_MAX - 1) || (q->max_els != 0 && q->num_els == q->max_els)) && q->new_data != 0)
				action(q->cond_put, q->mutex);
			if(q->new_data == 0) {
				return Q_ERR_NONEWDATA;
			}
		}
	}
	
	queue_element_t *new_el = (queue_element_t *)malloc(sizeof(queue_element_t));
	if(new_el == NULL) { 
		return Q_ERR_MEM;
	}
	new_el->data = el;
	new_el->next = NULL;
	
	if(q->sort == 0 || q->first_el == NULL) {
		if(q->last_el == NULL)
			q->first_el = new_el;
		else
			q->last_el->next = new_el;
		q->last_el = new_el;
	} else {
		queue_element_t *s = q->first_el;
		queue_element_t *t = NULL;
		int asc_first_el = q->asc_order != 0 && q->cmp_el(s->data, el) >= 0;
		int desc_first_el = q->asc_order == 0 && q->cmp_el(s->data, el) <= 0;
		
		if(asc_first_el == 0 && desc_first_el == 0) {
			for(s = q->first_el, t = s->next; s != NULL && t != NULL; s = t, t = t->next) {
				if(q->asc_order != 0 && q->cmp_el(s->data, el) <= 0 && q->cmp_el(el, t->data) <= 0) {
					break;
				} else if(q->asc_order == 0 && q->cmp_el(s->data, el) >= 0 && q->cmp_el(el, t->data) >= 0) {
					break;
				}
			}
			s->next = new_el;
			new_el->next = t;
			if(t == NULL)
				q->last_el = new_el;
		} else if(asc_first_el != 0 || desc_first_el != 0) {
			new_el->next = q->first_el;
			q->first_el = new_el;
		}
	}
	q->num_els++;
	pthread_cond_signal(q->cond_get);
	
	return Q_OK;
}

int8_t queue_get_internal(queue_t *q, void **e, int (*action)(pthread_cond_t *, pthread_mutex_t *), int (*cmp)(void *, void *), void *cmpel) {
	if(q == NULL) { 
		*e = NULL;
		return Q_ERR_INVALID;
	}
	if(q->num_els == 0) {
		if(action == NULL) {
			*e = NULL;
			return Q_ERR_NUM_ELEMENTS;
		} else {
			while(q->num_els == 0 && q->new_data != 0)
				action(q->cond_get, q->mutex);
			if (q->num_els == 0 && q->new_data == 0)
				return Q_ERR_NONEWDATA;
		}
	}
	queue_element_t *el_prev = NULL, *el = q->first_el;
	while(cmp != NULL && el != NULL && 0 != cmp(el, cmpel)) {
		el_prev = el;
		el = el->next;
	}
	
	if(el != NULL && el_prev == NULL) {
		q->first_el = el->next;
		if(q->first_el == NULL)
			q->last_el = NULL;
		q->num_els--;
		*e = el->data;
		free(el);
	} else if(el != NULL && el_prev != NULL) {
		el_prev->next = el->next;
		q->num_els--;
		*e = el->data;
		free(el);
	} else {
		*e = NULL;
		return Q_ERR_INVALID_ELEMENT;
	}
	pthread_cond_signal(q->cond_put);

	return Q_OK;
}
```
:::
1. `queue_lock_internal` 函數：
   - 用途：對佇列進行鎖定，防止多執行緒同時訪問。
   - 參數：`queue_t *q`，表示佇列的指標。
   - 返回值：鎖定成功返回 `Q_OK`，否則返回相應的錯誤碼。

2. `queue_unlock_internal` 函數：
   - 用途：對佇列進行解鎖，允許其他執行緒訪問佇列。
   - 參數：`queue_t *q`，表示佇列的指標。
   - 返回值：解鎖成功返回 `Q_OK`，否則返回相應的錯誤碼。

3. `queue_destroy_internal` 函數：
   - 用途：銷毀佇列，釋放相關資源。
   - 參數：`queue_t *q`，表示佇列的指標；`uint8_t fd`，表示某種標誌；`void (*ff)(void *)`，表示釋放函數的指標。
   - 返回值：成功返回 `Q_OK`，否則返回相應的錯誤碼。

4. `queue_flush_internal` 函數：
   - 用途：清空佇列中的元素，釋放相關資源。
   - 參數：`queue_t *q`，表示佇列的指標；`uint8_t fd`，表示某種標誌；`void (*ff)(void *)`，表示釋放函數的指標。
   - 返回值：成功返回 `Q_OK`，否則返回相應的錯誤碼。

5. `queue_put_internal` 函數：
   - 用途：將元素放入佇列中。
   - 參數：`queue_t *q`，表示佇列的指標；`void *el`，表示要放入佇列的元素；`int (*action)(pthread_cond_t *, pthread_mutex_t *)`，表示某種動作的函數指標。
   - 返回值：成功返回 `Q_OK`，否則返回相應的錯誤碼。

6. `queue_get_internal` 函數：
   - 用途：從佇列中取出符合條件的元素。
   - 參數：`queue_t *q`，表示佇列的指標；`void **e`，表示取出的元素的指標；`int (*action)(pthread_cond_t *, pthread_mutex_t *)`，表示某種動作的函數指標；`int (*cmp)(void *, void *)`，表示比較函數的指標；`void *cmpel`，表示比較的元素。
   - 返回值：成功返回 `Q_OK`，否則返回相應的錯誤碼。

請注意，這些函數中的錯誤碼（如 `Q_ERR_INVALID`、`Q_ERR_LOCK`、`Q_ERR_MEM` 等）用於指示相應的錯誤情況。此外，這些函數中包含了對多執行緒同步的機制，例如使用了 pthread 的 mutex 和條件變數。
:::spoiler example.c
- 完整程式碼
```c
#include <stdio.h>
#include <stdlib.h>
#include <queue.h>

typedef struct {
	char *test;
} test;

DEFINE_Q_GET(queue_get_test, test)//獲取元素
DEFINE_Q_DESTROY(queue_destroy_complete_test, test)

void free_test(test *t) {
	if(t->test != NULL)
        free(t->test);
	free(t);
}

int cmp_int_ptr(int *a, int *b) {
	if(*a < *b)
            return -1;
	else if(*a > *b)
            return 1;
	else
	    return 0;
}

void unsorted_mode() {
	queue_t *q = queue_create();
	
	char *t1 = (char *)malloc(1);
	char *t2 = (char *)malloc(2);
	char *t3 = (char *)malloc(4);
	char *t4 = (char *)malloc(8);
	
	test *s1 = (test *)malloc(sizeof(test));
	s1->test = t1; 
	test *s2 = (test *)malloc(sizeof(test));
	s2->test = t2; 
	test *s3 = (test *)malloc(sizeof(test));
	s3->test = t3; 
	test *s4 = (test *)malloc(sizeof(test));
	s4->test = t4; 
	
	queue_put(q, s1);
	queue_put(q, s2);
	queue_put(q, s3);
	queue_put(q, s4);
	
	test *t;
	queue_get_test(q, &t);
	free_test(t);
	queue_get_test(q, &t);
	free_test(t);
	
	queue_destroy_complete_test(q, free_test);
}

void sorted_mode() {
	queue_t *q = queue_create_sorted(1, (int (*)(void *, void *))cmp_int_ptr);
	
	int *t1 = (int *)malloc(sizeof(int));
	int *t2 = (int *)malloc(sizeof(int));
	int *t3 = (int *)malloc(sizeof(int));
	int *t4 = (int *)malloc(sizeof(int));
	
	*t1 = 10;
	*t2 = 12;
	*t3 = 1;
	*t4 = 1;
	
	queue_put(q, t1);
	queue_put(q, t2);
	queue_put(q, t3);
	queue_put(q, t4);
	
	int *t;
	queue_get(q, (void **)&t);
	printf("first int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("second int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("third int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("fourth int %i\n", *t);
	free(t);
	
	queue_destroy_complete(q, NULL);
}

void sorted2_mode() {
	queue_t *q = queue_create_limited_sorted(3, 1, (int (*)(void *, void *))cmp_int_ptr);
	
	int t1 = 1;
        queue_put(q, &t1);
	int t2 = 15;
        queue_put(q, &t2);
	int t3 = 3;
        queue_put(q, &t3);
	int t4 = 27;
        queue_put(q, &t4);
	int t5 = 9;
        queue_put(q, &t5);
  
        int *i;
        queue_get(q, (void **)&i);
        printf("first element was %d\n", *i);
        queue_get(q, (void **)&i);
        printf("second element was %d\n", *i);
        queue_get(q, (void **)&i);
        printf("third element was %d\n", *i);
        queue_get(q, (void **)&i);
        printf("fourth element was %p\n", i);
        queue_get(q, (void **)&i);
        printf("fifth element was %p\n", i);
  
        queue_destroy_complete(q, NULL);
}

int main(int argc, char *argv[]) {
	unsorted_mode();
	sorted_mode();
	sorted2_mode();
	
	return 0;
}
```
- free_test函數
    - 釋放test結構和其他相關內存
```c
void free_test(test *t) {
    if(t->test != NULL)
        free(t->test);
    free(t);
}
```
- cmp_int_ptr函數
    - 在queue中做排序
```c
int cmp_int_ptr(int *a, int *b) {
    if(*a < *b)
        return -1;
    else if(*a > *b)
        return 1;
    else
        return 0;
}
```
- unsorted_mode函數
    - 在非排序模式使用queue
```c
void unsorted_mode() {
	queue_t *q = queue_create();//建立queue
	
    //分配記憶體給字符指標變數
	char *t1 = (char *)malloc(1);
	char *t2 = (char *)malloc(2);
	char *t3 = (char *)malloc(4);
	char *t4 = (char *)malloc(8);
	
    //為測試結構分配記憶體
	test *s1 = (test *)malloc(sizeof(test));
	s1->test = t1; 
	test *s2 = (test *)malloc(sizeof(test));
	s2->test = t2; 
	test *s3 = (test *)malloc(sizeof(test));
	s3->test = t3; 
	test *s4 = (test *)malloc(sizeof(test));
	s4->test = t4; 
	
    //將test結構放入queue裡面
	queue_put(q, s1);
	queue_put(q, s2);
	queue_put(q, s3);
	queue_put(q, s4);
	
    //從queue中取出元素
	test *t;
	queue_get_test(q, &t);
	free_test(t);
	queue_get_test(q, &t);
	free_test(t);
	
    //完全銷毀佇列
    //使用 queue_destroy_complete_test 函數完全銷毀佇列，同時釋放佇列中所有元素所佔用的記憶體。
    //此函數的第二個參數是一個釋放函數，用於釋放每個元素的內存。在這裡，使用 free_test 函數來釋放 test 結構。
	queue_destroy_complete_test(q, free_test);
}
```
- sorted_mode函數
    - 在排序模式下使用queue
```c
void sorted_mode() {
    //建立排序佇列
	queue_t *q = queue_create_sorted(1, (int (*)(void *, void *))cmp_int_ptr);
	
    //分配記憶體給整數指標變數
	int *t1 = (int *)malloc(sizeof(int));
	int *t2 = (int *)malloc(sizeof(int));
	int *t3 = (int *)malloc(sizeof(int));
	int *t4 = (int *)malloc(sizeof(int));
	
	*t1 = 10;
	*t2 = 12;
	*t3 = 1;
	*t4 = 1;
	
    //將整數指標放入排序queue
	queue_put(q, t1);
	queue_put(q, t2);
	queue_put(q, t3);
	queue_put(q, t4);
	
    //從排序佇列中取出元素並在使用完畢後進行釋放
	int *t;
	queue_get(q, (void **)&t);
	printf("first int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("second int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("third int %i\n", *t);
	free(t);
	queue_get(q, (void **)&t);
	printf("fourth int %i\n", *t);
	free(t);
	
    //完全銷毀排序佇列
	queue_destroy_complete(q, NULL);
}
```
- sorted2_mode函數
    - 在有限排序模式下使用queue
```c
void sorted2_mode() {
    //建立有限排序queue
    //第1個參數是queue大小，第2個參數是每次插入時保留元素的數量，第3個參數是比較函數
	queue_t *q = queue_create_limited_sorted(3, 1, (int (*)(void *, void *))cmp_int_ptr);
	
    //將值放到queue裡面
	int t1 = 1;
    queue_put(q, &t1);
	int t2 = 15;
    ueue_put(q, &t2);
	int t3 = 3;
    queue_put(q, &t3);
	int t4 = 27;
    queue_put(q, &t4);
	int t5 = 9;
    queue_put(q, &t5);
  
    //將元素輸出
    //使用queue_get函數將元素取出
    int *i;
    queue_get(q, (void **)&i);
    printf("first element was %d\n", *i);
    queue_get(q, (void **)&i);
    printf("second element was %d\n", *i);
    queue_get(q, (void **)&i);
    printf("third element was %d\n", *i);
    queue_get(q, (void **)&i);
    printf("fourth element was %p\n", i);
    queue_get(q, (void **)&i);
    printf("fifth element was %p\n", i);
  
    //銷毀queue
	queue_destroy_complete(q, NULL);
}
```
:::





    
