環形消息隊列的實現

struct MessageQueue
{
 int* m_pArray;

 //消息隊列長度
 int m_iLength;

 //消息隊列的讀下標
 int m_iRead;

 //消息隊列的寫下標
 int m_iWrite;

 //多個寫操作時的互斥鎖
 pthread_mutex_t m_mutex;

 //該消息隊列的條件變量
 pthread_cond_t m_cond;
};

MessageQueue* ip_create_messagequeue(int length)
{
 MessageQueue* pMessageQueue = (MessageQueue*)malloc(sizeof(MessageQueue));

 if (NULL == pMessageQueue)
 {
  #ifdef _LOG
   printf("%s : %d get memory is NULL", __FILE__, __LINE__);
  #else
   WRITELOG(ErrLog, "%s : %d get memory is NULL", __FILE__, __LINE__);
  #endif
 
  return NULL;
 }
 else
 {
  //增加一個長度
  length++;
 
  pMessageQueue ->m_pArray = (int*)malloc(sizeof(int) * length);

  if (NULL == pMessageQueue ->m_pArray)
  {
   #ifdef _LOG
    printf("%s : %d get memory is NULL", __FILE__, __LINE__);
   #else
    WRITELOG(ErrLog, "%s : %d get memory is NULL", __FILE__, __LINE__);
   #endif
  
   free(pMessageQueue);

   return NULL;
  }
  else
  {
   memset(pMessageQueue ->m_pArray, 0, length * sizeof(int));

   pMessageQueue ->m_iLength = length;
   pMessageQueue ->m_iRead = pMessageQueue ->m_iWrite = 0;

   //初始化互斥鎖
   pthread_mutex_init(&(pMessageQueue ->m_mutex), NULL);

   pthread_cond_init(&(pMessageQueue ->m_cond), NULL);

   return pMessageQueue;
  }
 }
}

//增加一個
bool ip_in_messagequeue(MessageQueue* pMessageQueue, int value)
{
 assert(NULL != pMessageQueue);
 
 int saveRead = pMessageQueue ->m_iRead;

 //寫下標在讀下標之前
 if (pMessageQueue ->m_iWrite >= saveRead)
 {
  //寫下標在讀下標前面已滿的情況只有讀下標在原地
  //或者寫下標在末尾,讀下標前進了一位
  //消息隊列已滿
  if ((pMessageQueue ->m_iWrite - pMessageQueue ->m_iRead) == pMessageQueue ->m_iLength - 2)
  {
   return false;
  }
 
  
  /*if ((pMessageQueue ->m_iWrite + 1 == pMessageQueue ->m_iLength - 1)
  && (pMessageQueue ->m_iRead == 0))
  {
   return false;
  }

  if ((pMessageQueue ->m_iWrite == pMessageQueue ->m_iLength -1)
  && (pMessageQueue ->m_iRead == 1))
  {
   return false;
  }*/
 }
 //寫下標在讀下標之後
 else
 {
  //寫下標和讀下標之間的距離間隔1, 表示隊列已滿
  if (saveRead -pMessageQueue ->m_iWrite == 1)
  {
   return false;
  }
 }

 //寫入消息
 (pMessageQueue ->m_pArray)[pMessageQueue ->m_iWrite] = value;

 //已經寫到數組末尾
 if (pMessageQueue ->m_iWrite == pMessageQueue ->m_iLength - 1)
 {
  pMessageQueue ->m_iWrite = 0;
 }
 else
 {
  //寫下標前進一位
  ++(pMessageQueue ->m_iWrite);
 }

 return true;
}

 

//當寫下標和讀下標重合,表示沒有數據可讀,寫下標不可能追上讀下標,
//讀下標可以和寫下標重合
int ip_get_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 int saveWrite = pMessageQueue ->m_iWrite;

 
 //無數據可讀
 if (saveWrite == pMessageQueue ->m_iRead)
 {
  return -1;
 }
 //寫下標在讀下標的前面
 else if (saveWrite > pMessageQueue ->m_iRead)
 {
  int iResult = (pMessageQueue ->m_pArray)[pMessageQueue ->m_iRead];
 
  ++(pMessageQueue ->m_iRead); 
 
  return iResult;
 }
 //寫下標在讀下標的後面
 else
 {
  int iResult = 0;
 
  //剛好讀到數組尾
  if (pMessageQueue ->m_iRead == pMessageQueue ->m_iLength - 1)
  {
   iResult = (pMessageQueue ->m_pArray)[pMessageQueue ->m_iLength - 1];

   pMessageQueue ->m_iRead = 0;

   return iResult;
  }

  iResult = (pMessageQueue ->m_pArray)[pMessageQueue ->m_iRead];

  ++(pMessageQueue ->m_iRead); 
 
  return iResult;
 }
}


void ip_addlock_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 pthread_mutex_lock(&(pMessageQueue ->m_mutex));
}


void ip_unlock_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 pthread_mutex_unlock(&(pMessageQueue ->m_mutex));
}

void ip_signal_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 pthread_cond_signal(&(pMessageQueue ->m_cond));
}

void ip_wait_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 timespec mytime;
 mytime.tv_sec = time(NULL)+1;  //Wait for 1 second, Must 
 mytime.tv_nsec = 0;
 
 pthread_cond_timedwait(&(pMessageQueue ->m_cond), &(pMessageQueue ->m_mutex), (const struct timespec *)&mytime);
}

bool ip_isempty_messagequeue(MessageQueue* pMessageQueue)
{
 assert(NULL != pMessageQueue);

 if (pMessageQueue ->m_iWrite == pMessageQueue ->m_iRead)
 {
  return true;
 }
 else
 {
  return false;
 }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章