重构
This commit is contained in:
+59
-93
@@ -1,129 +1,95 @@
|
||||
#include <c_LinkQueue.h>
|
||||
#include <c_Memory.h>
|
||||
#include "c_Alignment.h"
|
||||
#include "c_Macros.h"
|
||||
|
||||
c_err_t c_LinkQueue_Init(c_LinkQueue_t* self, int obj_size) {
|
||||
if (!self || obj_size == 0) return C_ERR_PARAM;
|
||||
// 原地初始化:无哨兵模式,初始化 head 和 tail 全部指向 0
|
||||
c_err_t c_LinkQueue_Init(c_LinkQueue_t* self, c_size_t item_size, c_Allocator_t* allocator) {
|
||||
if (!self || item_size == 0) return C_ERR_PARAM;
|
||||
|
||||
self->allocator = (allocator != NULL) ? *allocator : c_DefaultAllocator;
|
||||
self->item_size = item_size;
|
||||
self->size = 0;
|
||||
self->head = NULL;
|
||||
self->tail = NULL;
|
||||
self->obj_size = (int)obj_size;
|
||||
self->size = 0;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void c_LinkQueue_Destroy(c_LinkQueue_t* self) {
|
||||
if (!self) return;
|
||||
// 入队操作 (基于二级指针的完美 O(1) 极致分支优化)
|
||||
c_err_t c_LinkQueue_Enqueue(c_LinkQueue_t* self, const void* item) {
|
||||
if (!self || !item) return C_ERR_PARAM;
|
||||
|
||||
c_LinkQueueNode_t* current = self->head;
|
||||
while (current != NULL) {
|
||||
c_LinkQueueNode_t* next = current->next;
|
||||
C_FREE(current);
|
||||
current = next;
|
||||
}
|
||||
self->head = NULL;
|
||||
self->tail = NULL;
|
||||
self->size = 0;
|
||||
}
|
||||
|
||||
c_err_t c_LinkQueue_Push(c_LinkQueue_t* self, void* obj) {
|
||||
if (!self || !obj) return C_ERR_PARAM;
|
||||
|
||||
// 1. 配置新節點與資料空間
|
||||
int size = (int)sizeof(c_LinkQueueNode_t) + self->obj_size;
|
||||
size = C_ALIGN_UPB(size, C_ALIGN_SIZE);
|
||||
c_LinkQueueNode_t* new_node = (c_LinkQueueNode_t*)C_ALLOC(size);
|
||||
// 1. 分配变长节点空间 (控制壳 + 业务数据一体化)
|
||||
c_size_t total_bytes = sizeof(c_LinkQueueNode_t) + self->item_size;
|
||||
c_LinkQueueNode_t* new_node = (c_LinkQueueNode_t*)c_Allocator_Alloc(&self->allocator, total_bytes);
|
||||
if (!new_node) return C_ERR_NOMEM;
|
||||
new_node->data = new_node+1;
|
||||
|
||||
// 深複製資料內容
|
||||
memcpy(new_node->data, obj, self->obj_size);
|
||||
new_node->next = NULL;
|
||||
memcpy(QUEUE_NODE_DATA(new_node), item, self->item_size); // 泛型值深度复制
|
||||
|
||||
// 2. 將新節點追加到串列尾端
|
||||
if (self->tail == NULL) {
|
||||
// 佇列原本為空
|
||||
self->head = new_node;
|
||||
self->tail = new_node;
|
||||
} else {
|
||||
// 佇列不為空,讓原本尾端的 next 指向新節點,並更新 tail
|
||||
self->tail->next = new_node;
|
||||
self->tail = new_node;
|
||||
}
|
||||
// 2. 【二级指针艺术】:消灭空队列插入的分支
|
||||
// 如果队列为空,新节点应该挂在 head 上;如果不为空,新节点应该挂在 tail->next 上
|
||||
c_LinkQueueNode_t** pp = (self->head == NULL) ? &(self->head) : &(self->tail->next);
|
||||
|
||||
// 一行代码,完美完成旧拓扑到新节点的挂接
|
||||
*pp = new_node;
|
||||
|
||||
// 3. 将尾指针直接移到最新插入的节点上,自愈性推进
|
||||
self->tail = new_node;
|
||||
self->size++;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
c_err_t c_LinkQueue_Pop(c_LinkQueue_t* self, void* obj) {
|
||||
if (!self ) return C_ERR_PARAM;
|
||||
if (self->size == 0 || !self->head) return C_ERR_EMPTY;
|
||||
// 出队操作 (O(1) 性能,完美防御下溢)
|
||||
c_err_t c_LinkQueue_Dequeue(c_LinkQueue_t* self, void* out_item) {
|
||||
if (!self || self->size == 0 || !self->head) return C_ERR_OUTOFBOUND;
|
||||
|
||||
c_LinkQueueNode_t* to_delete = self->head;
|
||||
// 锁定队头即将被剔除解体的物理节点
|
||||
c_LinkQueueNode_t* node_to_free = self->head;
|
||||
|
||||
// 1. 複製資料到使用者緩衝區
|
||||
if (obj) {
|
||||
memcpy(obj, to_delete->data, self->obj_size);
|
||||
// 如果用户需要拷出快照副本,执行深度拷贝
|
||||
if (out_item) {
|
||||
memcpy(out_item, QUEUE_NODE_DATA(node_to_free), self->item_size);
|
||||
}
|
||||
|
||||
// 2. 將 head 移至下一個節點
|
||||
self->head = to_delete->next;
|
||||
// 队头指针向后大步滑进一格
|
||||
self->head = node_to_free->next;
|
||||
|
||||
// 边界特殊维护:如果出队后队列彻底被掏空了,尾指针 tail 必须安全地缩回 NULL
|
||||
if (self->head == NULL) {
|
||||
self->tail = NULL;
|
||||
}
|
||||
|
||||
// 3. 釋放斷開的節點資源
|
||||
C_FREE(to_delete);
|
||||
|
||||
// 闭环退还包装内存壳
|
||||
c_Allocator_Free(&self->allocator, node_to_free);
|
||||
self->size--;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
c_err_t c_LinkQueue_Peek(c_LinkQueue_t* self, void* obj) {
|
||||
if (!self ) return C_ERR_PARAM;
|
||||
if (self->size == 0 || !self->head) return C_ERR_EMPTY;
|
||||
|
||||
// 複製最前端的資料內容
|
||||
if (obj) {
|
||||
memcpy(obj, self->head->data, self->obj_size);
|
||||
}
|
||||
return C_ERR_OK;
|
||||
// 查看队头元素 (只读原位窥探,零拷贝损耗)
|
||||
void* c_LinkQueue_Peek(const c_LinkQueue_t* self) {
|
||||
if (!self || self->size == 0 || !self->head) return NULL;
|
||||
return QUEUE_NODE_DATA(self->head);
|
||||
}
|
||||
|
||||
void c_LinkQueueIter_Remove(c_LinkQueueIter_t* self) {
|
||||
if (!self || !self->queue || !self->node || !*(self->node)) return;
|
||||
// 高效清空队列
|
||||
void c_LinkQueue_Clear(c_LinkQueue_t* self) {
|
||||
if (!self) return;
|
||||
|
||||
c_LinkQueueNode_t* to_delete = *(self->node);
|
||||
c_LinkQueue_t* q = self->queue;
|
||||
|
||||
// 檢查目前要刪除的是否為尾端節點
|
||||
const c_bool_t is_tail = (to_delete == q->tail);
|
||||
|
||||
// 讓上一個節點的 next(或 head)直接指向下一個節點,將 to_delete 從串列中斷開
|
||||
*(self->node) = to_delete->next;
|
||||
|
||||
// 如果刪除的是尾端節點,必須更新 tail 指標
|
||||
if (is_tail) {
|
||||
if (q->head == NULL) {
|
||||
// 情況 A:刪除後佇列完全空了
|
||||
q->tail = NULL;
|
||||
} else {
|
||||
// 情況 B:刪除的是尾巴,但前方還有元素。
|
||||
// 沿著 head 重新走訪一遍,找出現在最尾端的節點(即 next 為 NULL 的節點)
|
||||
c_LinkQueueNode_t* curr = q->head;
|
||||
while (curr->next != NULL) {
|
||||
curr = curr->next;
|
||||
}
|
||||
q->tail = curr; // 更新新的尾端
|
||||
}
|
||||
c_LinkQueueNode_t* curr = self->head;
|
||||
while (curr) {
|
||||
c_LinkQueueNode_t* next_to_free = curr->next;
|
||||
c_Allocator_Free(&self->allocator, curr);
|
||||
curr = next_to_free;
|
||||
}
|
||||
|
||||
// 釋放記憶體資源
|
||||
C_FREE(to_delete);
|
||||
self->head = NULL;
|
||||
self->tail = NULL;
|
||||
self->size = 0;
|
||||
}
|
||||
|
||||
// 同步遞減佇列大小
|
||||
q->size--;
|
||||
|
||||
// 此時 self->node 已自動留在原本的下一個節點上,呼叫端可直接繼續 Get() 或 Next()
|
||||
}
|
||||
// 彻底销毁
|
||||
void c_LinkQueue_Destroy(c_LinkQueue_t* self) {
|
||||
if (!self) return;
|
||||
c_LinkQueue_Clear(self);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user