/**********************************************************************
* 版权所有 (C)2022,huangyuxiang
*
* 文件名称：QueueUse.c
* 文件标识：无
* 内容摘要：示例队列的使用(入队和出队)
* 其它说明：无
* 当前版本：V1.0
* 作    者：huangyuxiang
* 完成日期：20220617
*
**********************************************************************/
#include <stdio.h>
#include <string.h>
#include <ftw.h>
#include <pthread.h>
#include <stdint.h>
#include <time.h>
#include "queue.h" 

//全局变量定义
T_StructInfo g_tQueue[MAX_QUEUE] = {0};      // 队列结构体
M_StructInfo g_mQueue[MAX_QUEUE] = {0};      // 队列结构体
UINT32 g_iQueueHead = 0;                     // 队列头部索引
UINT32 g_iQueueTail = 0;                     // 队列尾部索引
UINT32 g_imQueueHead = 0;                     // 队列头部索引
UINT32 g_imQueueTail = 0;                     // 队列尾部索引
pthread_mutex_t     g_mutex_queue_cs;        // 互斥信号量
pthread_cond_t      queue_cv;
pthread_mutexattr_t g_MutexAttr;
pthread_mutex_t     g_mutex_queue_cs_m;        // 互斥信号量
pthread_cond_t      queue_cv_m;
pthread_mutexattr_t g_MutexAttr_m;
 
/****************************************************************
* 功能描述: 将数据加入队列中
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无 
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
****************************************************************/
void PutDataIntoQueue(uint32_t tagname,uint16_t battery){
    T_StructInfo tQueueData = {0};
 
    // 对结构体的变量进行赋值
    //memcpy(tQueueData.cellNum,cellNum,4);
    //memcpy(tQueueData.cmd,cmd,4);
    tQueueData.tagname=tagname;
    tQueueData.battery=battery;
    // 将数据加入队列(一直等到加入成功之后才退出)
    while (EnQueue(tQueueData) == -1){
        Sleep(1000);       // 加入失败,1秒后重试
    }
 
    // 打印加入的数据
    //printf("PutDataIntoQueue: cellNum=%s, cmd=%s\n", tQueueData.cellNum, tQueueData.cmd);
}
 
void PutDataIntoMQueue(char *payload){
    M_StructInfo mQueueData = {0};
 
    // 对结构体的变量进行赋值
    memcpy(mQueueData.payload,payload,1024);
 
    // 将数据加入队列(一直等到加入成功之后才退出)
    while (EnMQueue(mQueueData) == -1){
        Sleep(1000);       // 加入失败,1秒后重试
    }
 
    // 打印加入的数据
    //printf("PutDataIntoMQueue: payload=%s\n", mQueueData.payload);
}
/****************************************************************
* 功能描述: 将数据取出队列中
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
****************************************************************/
int GetDataFromQueue(uint32_t *tagname,uint16_t *battery){
    T_StructInfo tQueueData = {0};
    if (DeQueue(&tQueueData) == -1){
        return -1;
    }
    //memcpy(cellNum,tQueueData.cellNum,4);
    //memcpy(cmd,tQueueData.cmd,4);
    *tagname=tQueueData.tagname;
    *battery=tQueueData.battery;
    // 打印取出的数据
    //printf("GetDataFromQueue: cellNum=%s, cmd=%s\n", tQueueData.cellNum, tQueueData.cmd);
    return 0;
}
 
int GetDataFromMQueue(char *payload){
    M_StructInfo mQueueData = {0};
    if (DeMQueue(&mQueueData) == -1){
        return -1;
    }
    memcpy(payload,mQueueData.payload,1024);
    // 打印取出的数据
    //printf("GetDataFromMQueue: payload=%s\n", mQueueData.payload);
    return 0;
}
/****************************************************************
* 功能描述: 数据入队列
* 输入参数: tQueueData-队列数据
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
****************************************************************/
INT32 EnQueue(T_StructInfo tQueueData){
    INT32  iRetVal  = 0;
    UINT32 iNextPos = 0;
 
    pthread_mutex_lock(&g_mutex_queue_cs);
    iNextPos = g_iQueueTail + 1;
 
    if (iNextPos >= MAX_QUEUE){
        iNextPos = 0;
    }
 
    if (iNextPos == g_iQueueHead){
        iRetVal = -1;   // 已达到队列的最大长度
    }else{
        // 入队列
        memset(&g_tQueue[g_iQueueTail], 0x00,  sizeof(T_StructInfo));
        memcpy(&g_tQueue[g_iQueueTail], &tQueueData, sizeof(T_StructInfo));
        g_iQueueTail = iNextPos;
    }
 
    pthread_cond_signal(&queue_cv);
    pthread_mutex_unlock(&g_mutex_queue_cs);
 
    return iRetVal;
}
 
INT32 EnMQueue(M_StructInfo mQueueData){
    INT32  iRetVal  = 0;
    UINT32 iNextPos = 0;
 
    pthread_mutex_lock(&g_mutex_queue_cs_m);
    iNextPos = g_imQueueTail + 1;
 
    if (iNextPos >= MAX_QUEUE){
        iNextPos = 0;
    }
 
    if (iNextPos == g_imQueueHead){
        iRetVal = -1;   // 已达到队列的最大长度
    }else{
        // 入队列
        memset(&g_mQueue[g_imQueueTail], 0x00,  sizeof(M_StructInfo));
        memcpy(&g_mQueue[g_imQueueTail], &mQueueData, sizeof(M_StructInfo));
        g_imQueueTail = iNextPos;
    }
 
    pthread_cond_signal(&queue_cv_m);
    pthread_mutex_unlock(&g_mutex_queue_cs_m);
 
    return iRetVal;
}
/****************************************************************
* 功能描述: 数据出队列
* 输入参数: ptStructData-队列数据
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
****************************************************************/
INT32 DeQueue(T_StructInfo *ptStructData){
    T_StructInfo tQueueData = {0};
 
    if (ptStructData == NULL){
        return -1;
    }
 
    pthread_mutex_lock(&g_mutex_queue_cs);
    while (g_iQueueHead == g_iQueueTail){
        pthread_cond_wait(&queue_cv, &g_mutex_queue_cs);
    }
 
 
    memset(&tQueueData, 0x00, sizeof(T_StructInfo));
    memcpy(&tQueueData, &g_tQueue[g_iQueueHead], sizeof(T_StructInfo));
    g_iQueueHead ++;
 
    if (g_iQueueHead >= MAX_QUEUE){
        g_iQueueHead = 0;
    }
 
    pthread_mutex_unlock(&g_mutex_queue_cs);
    memcpy(ptStructData, &tQueueData, sizeof(T_StructInfo));
 
    return 0;
}

INT32 DeMQueue(M_StructInfo *mDqueueData){
    M_StructInfo mQueueData = {0};
 
    if (mDqueueData == NULL){
        return -1;
    }
 
    pthread_mutex_lock(&g_mutex_queue_cs_m);
    while (g_imQueueHead == g_imQueueTail){
        pthread_cond_wait(&queue_cv_m, &g_mutex_queue_cs_m);
    }
 
 
    memset(&mQueueData, 0x00, sizeof(M_StructInfo));
    memcpy(&mQueueData, &g_mQueue[g_imQueueHead], sizeof(M_StructInfo));
    g_imQueueHead ++;
 
    if (g_imQueueHead >= MAX_QUEUE){
        g_imQueueHead = 0;
    }
 
    pthread_mutex_unlock(&g_mutex_queue_cs_m);
    memcpy(mDqueueData, &mQueueData, sizeof(M_StructInfo));
 
    return 0;
}
/**********************************************************************
* 功能描述： 程序休眠
* 输入参数： iCountMs-休眠时间(单位:ms)
* 输出参数： 无
* 返 回 值： 无
* 其它说明： 无
* 修改日期      版本号       修改人        修改内容
********************************************************************/ 
void Sleep(UINT32 iCountMs){
    struct timeval t_timeout = {0};
 
    if (iCountMs < 1000){
        t_timeout.tv_sec  = 0;
        t_timeout.tv_usec = iCountMs * 1000;
    }else{
        t_timeout.tv_sec  = iCountMs / 1000;
        t_timeout.tv_usec = (iCountMs % 1000) * 1000;
    }
    select(0, NULL, NULL, NULL, &t_timeout);    // 调用select函数阻塞程序
}
