[00033]-[2017-04-15]-[00]-[C语言的一种泛型队列(Heap List)的实现(采用内存Buffer,非系统Heap动态分配处理)]

/*

  FileName:     Base_List.h 

  Author:     Ares

  Date:      2017-04-15

*/

#ifndef _BASE_LIST_H_
#define _BASE_LIST_H_

#include "my_typedef.h"
#include <unistd.h>
#include <pthread.h>

#define LIST_NODE_ATTR_IS_USED 0x00000001
#define NODE_INDEX_END 0xFFFFFFFF

typedef struct _BASE_LIST_T{
u32 Node_Amount;
u32 First_Index;
u32 Last_Index;
u32 Cur_Index;
u32 Body_Size;
u32 Heap_Size;
pthread_mutex_t Mutex;
}BASE_LIST_T;

typedef BASE_LIST_T* PBASE_LIST_T;

typedef struct _BASE_NODE_T{
u32 Next;
u32 Prev;
u32 Attr;
}BASE_NODE_T;

typedef BASE_NODE_T* PBASE_NODE_T;

#define LIST_T(NodeBody_T, HeapSize) struct _LIST_T{\
u32 Node_Amount;\
u32 First_Index;\
u32 Last_Index;\
u32 Cur_Index;\
u32 Body_Size;\
u32 Heap_Size;\
pthread_mutex_t Mutex;\
struct _NODE_T{\
u32 Next;\
u32 Prev;\
u32 Attr;\
NodeBody_T Node_Body;\
}Node_Heap[HeapSize];}

void LIST_NODE_DEF_SHOW(PVOID p);
void LIST_NODE_DEF_Del(PVOID p, u32 Index);
u32 LIST_NODE_DEF_Add(PVOID p);
void LIST_T_DEF_INIT(PVOID p, int BodySize, int HeapSize);

#endif

 

 

/*

  FileName:     Base_List.c

  Author:     Ares

  Date:      2017-04-15

*/

#include "Base_List.h"

/*
  Base_List 默认初始化函数
*/
void LIST_T_DEF_INIT(PVOID p, int BodySize, int HeapSize)
{
  u32 i = 0;
  u32 NodeSize = sizeof(BASE_NODE_T)+BodySize;
  PBASE_LIST_T pBaseList = (PBASE_LIST_T)p;
  PBASE_NODE_T pBaseNode = (PBASE_NODE_T)(p+sizeof(BASE_LIST_T));
  PBASE_NODE_T pTmpNode = NULL;

  pBaseList->Node_Amount = 0;
  pBaseList->First_Index = 0;
  pBaseList->Last_Index = 0;
  pBaseList->Node_Amount = 0;
  pBaseList->Body_Size = BodySize;
  pBaseList->Heap_Size = HeapSize;


  pthread_mutex_init(&pBaseList->Mutex, NULL); // 初始化互斥锁 多线程访问的时候 有好处 防止写冲突

  pTmpNode = pBaseNode;
  for(i = 0; i < HeapSize; i++)
  {
    memset(pBaseNode, 0, NodeSize);
    pTmpNode = (PBASE_NODE_T)(pBaseNode+NodeSize*i);
  }
}

/*
  Base_List 节点添加函数
  队列节点添加 -> 首先需要从Heap[]中分配节点,然后在添加到队列中去
*/
u32 LIST_NODE_DEF_Add(PVOID p)
{
  u32 i = 0;
  u32 Index = 0;
  u32 Node_Offset = 0;
  u32 Node_Size = 0;
  u32 BodySize = 0;
  u32 HeapSize = 0;
  PBASE_LIST_T pBaseList = (PBASE_LIST_T)p;
  PBASE_NODE_T pBaseNode = (PBASE_NODE_T)(p+sizeof(BASE_LIST_T));
  PBASE_NODE_T pTmpNode = NULL;
  PBASE_NODE_T pLastNode = NULL;

  // 上锁 申请访问
  pthread_mutex_lock(&pBaseList->Mutex);

  /* --------------------------------------------------------------- */

  BodySize = pBaseList->Body_Size;
  HeapSize = pBaseList->Heap_Size;
  Node_Size = BodySize+sizeof(BASE_NODE_T);

  if(pBaseList->Node_Amount >= (HeapSize-1)) // [0] [1] [2] [3] [4] ..... [HeapSize-1] 其中 [0] 不使用 一直空置着 所以Heap能够分配的就是HeapSize-1 个节点
  {
    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return 0; // 表示分配节点失败
  }
  if(pBaseList->Node_Amount == 0) // 还没有分配节点 从[1] 开始分配节点
  {
    pBaseList->First_Index = 1; // 队列的头索引
    pBaseList->Last_Index = 1; // 队列的尾索引
    pBaseList->Cur_Index = 1; // 队列的当前分配索引 用于分配使用的
    pBaseList->Node_Amount = 1;
    Node_Offset = 0+Node_Size*1;
    pBaseNode = pBaseNode + Node_Offset;
    memset(pBaseNode, 0, Node_Size);
    pBaseNode->Attr = LIST_NODE_ATTR_IS_USED;
    pBaseNode->Prev = 0;
    pBaseNode->Next = NODE_INDEX_END;

    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return 1;
  }
  else
  {
    i = pBaseList->Cur_Index+1;
    if(i>=HeapSize)
    {
      i = 1;
    }
    Node_Offset = Node_Size*i;
    pTmpNode = pBaseNode + Node_Offset;

    while((pTmpNode->Attr&LIST_NODE_ATTR_IS_USED))
    {
      i = i+1;
      if(i>=HeapSize)
      {
        i = 1;
      }
      Node_Offset = Node_Size*i;
      pTmpNode = pBaseNode + Node_Offset;
    }

    // 找到了未被使用的节点 可以分配
    pTmpNode->Attr = LIST_NODE_ATTR_IS_USED;
    pBaseList->Cur_Index = i;
    Index = i; // 保存当前节点的索引值

    // 现在开始进行队列的插入动作了
    // 定位到队列的尾部节点处 修改尾部节点的Next索引值
    i = pBaseList->Last_Index;
    Node_Offset = Node_Size*i;
    pLastNode = pBaseNode + Node_Offset;
    pTmpNode->Prev = i;
    pLastNode->Next = Index;
    pTmpNode->Next = NODE_INDEX_END;
    pBaseList->Last_Index = Index;
    pBaseList->Node_Amount++;

    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return Index;
  }
}

/*
  Base_List 节点删除函数
  队列节点删除 -> 首先将节点从队列中删除, 然后从Heap[]中销毁掉标志
*/
void LIST_NODE_DEF_Del(PVOID p, u32 Index)
{
  u32 i = 0;
  u32 Tmp_Index = 0;
  u32 Prev_Index = 0;
  u32 Next_Index = 0;
  u32 Node_Offset = 0;
  u32 Node_Size = 0;
  u32 BodySize = 0;
  u32 HeapSize = 0;
  PBASE_LIST_T pBaseList = (PBASE_LIST_T)p;
  PBASE_NODE_T pBaseNode = (PBASE_NODE_T)(p+sizeof(BASE_LIST_T));
  PBASE_NODE_T pTmpNode = NULL;
  PBASE_NODE_T pFirstNode = NULL;
  PBASE_NODE_T pLastNode = NULL;
  BodySize = pBaseList->Body_Size;
  HeapSize = pBaseList->Heap_Size;
  Node_Size = BodySize+sizeof(BASE_NODE_T);

  // 上锁 申请访问
  pthread_mutex_lock(&pBaseList->Mutex);

  if(Index==0 || (Index >= HeapSize))
  {
    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return;
  }

  if(pBaseList->Node_Amount == 0)
  {
    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return; // 队列已经是空的了 不需要删除节点
  }

  // 首先要定位到这个节点处
  Node_Offset = Node_Size*Index;
  pTmpNode = pBaseNode + Node_Offset;

  if((pTmpNode->Attr&LIST_NODE_ATTR_IS_USED)==0) // 此节点不是被占用 说明Index 是不合法的
  {
    printf("Node_Heap[%d].Attr != LIST_NODE_ATTR_IS_USED. \n", Index);
    // 释放锁 退出访问
    pthread_mutex_unlock(&pBaseList->Mutex);
    return;
  }

  // 如果删除的是唯一的节点 Prev = 0 Next = 0xFFFFFFFF
  if((pBaseList->Node_Amount==1))
  {
    if((pTmpNode->Prev==0) && (pTmpNode->Next==NODE_INDEX_END))
    {
      // 直接初始化这个队列Heap
      LIST_T_DEF_INIT(p, BodySize, HeapSize);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
    else
    {
      // 队列中的节点是唯一的 但是要删除的节点的索引是不对的
      printf("pBaseList->Node_Amount=1 But Node_Heap[%d] Prev = %d Next = %d. \n", Index, pTmpNode->Prev, pTmpNode->Next);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
  }

  // 到此处 说明 pBaseList->Node_Amount > 1
  if(pTmpNode->Prev==0) // 该节点是队列的头节点
  {
    // 不必考虑单个节点的情况 因为前面已经直接过滤掉了
    if(pBaseList->First_Index != Index)
    {
      // 该节点是队列的头节点 但是队列的头节点索引 没有指向这个节点 说明出错了 要报错
      printf("Node_Heap[%d].Prev == 0 But pBaseList->First_Index = %d. \n", Index, pBaseList->First_Index);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
    else
    {
      Tmp_Index = pTmpNode->Next;
      Node_Offset = Node_Size*Tmp_Index;
      pFirstNode = pBaseNode + Node_Offset;
      pFirstNode->Prev = 0;
      pBaseList->First_Index = pTmpNode->Next;
      pBaseList->Node_Amount--;
      memset(pTmpNode, 0, Node_Size);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
  }

  if(pTmpNode->Next==NODE_INDEX_END) // 该节点是队列的尾节点
  {
    // 不必考虑单个节点的情况 因为前面已经直接过滤掉了
    if(pBaseList->Last_Index!= Index)
    {
      // 该节点是队列的尾节点 但是队列的尾节点索引 没有指向这个节点 说明出错了 要报错
      printf("Node_Heap[%d].Next == 0 But pBaseList->Last_Index = %d. \n", Index, pBaseList->First_Index);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
    else
    {
      Tmp_Index = pTmpNode->Prev;
      Node_Offset = Node_Size*Tmp_Index;
      pLastNode = pBaseNode + Node_Offset;
      pLastNode->Next = NODE_INDEX_END;
      pBaseList->Last_Index = pTmpNode->Prev;
      pBaseList->Node_Amount--;
      memset(pTmpNode, 0, Node_Size);
      // 释放锁 退出访问
      pthread_mutex_unlock(&pBaseList->Mutex);
      return;
    }
  }

  // 既不是头节点 也不是尾节点
  Prev_Index= pTmpNode->Prev;
  Node_Offset = Node_Size*Prev_Index;
  pFirstNode = pBaseNode + Node_Offset; // 后驱节点
  Next_Index = pTmpNode->Next;
  Node_Offset = Node_Size*Next_Index;
  pLastNode = pBaseNode + Node_Offset; // 前驱节点
  pFirstNode->Next = Next_Index; // 设置前驱节点的后驱索引
  pLastNode->Prev = Prev_Index; // 设置后驱节点的前驱索引
  memset(pTmpNode, 0, Node_Size);
  pBaseList->Node_Amount--;
  // 释放锁 退出访问
  pthread_mutex_unlock(&pBaseList->Mutex);
  return;
}

/*
  Base_List 显示函数
*/
void LIST_NODE_DEF_SHOW(PVOID p)
{
  u32 Index = 0;
  u32 Node_Size = 0;
  u32 BodySize = 0;
  u32 HeapSize = 0;
  PBASE_LIST_T pBaseList = (PBASE_LIST_T)p;
  PBASE_NODE_T pBaseNode = (PBASE_NODE_T)(p+sizeof(BASE_LIST_T));
  PBASE_NODE_T pTmpNode = NULL;

  // 上锁 申请访问
  pthread_mutex_lock(&pBaseList->Mutex);

  BodySize = pBaseList->Body_Size;
  HeapSize = pBaseList->Heap_Size;
  Node_Size = BodySize+sizeof(BASE_NODE_T);

  if(pBaseList->Node_Amount == 0)
  {
    return;
  }

  Index = pBaseList->First_Index;
  pTmpNode = pBaseNode + Node_Size*Index;
  while(Index != NODE_INDEX_END)
  {
    printf("PrevIndex = %d Index = %d NextIndex = %d\n", pTmpNode->Prev, Index, pTmpNode->Next);
    Index = pTmpNode->Next;
    pTmpNode = pBaseNode + Node_Size*Index;
  }
  // 释放锁 退出访问
  pthread_mutex_unlock(&pBaseList->Mutex);
  return;
}

 

posted @ 2017-04-15 23:55  Auris  阅读(465)  评论(0编辑  收藏  举报