queue

队列push/pop

在这里插入图片描述

queue.h

#ifndef _QUEUE_H__
#define _QUEUE_H__

#include <vector>
#include <mutex>

#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */

typedef enum {
    DATA_IDLE,
    DATA_BUSY,
}E_STATUS;

typedef enum {
    SUCCESS=0,
    HEAD_DATA_NULL,
    QUEUE_FULL,
    NOT_IDLE,
    COPY_FAILED,
    QUEUE_EMPTY
}E_NODE_OP;

typedef struct _img_info{
        int width;
        int height;
        int chn;
        int rate;
}img_info;

typedef struct node_data
{
        E_STATUS status;
        unsigned int mem_size;
        unsigned char *mem;
        bool first;
}vibe_data;

typedef struct tag_node
{
    vibe_data data;
    struct tag_node *next;
}vibe_node;

typedef struct
{
        int queue_index;
        int queue_len;
        int push_interval;//ms
        int pop_interval;//ms
        img_info info;
        vibe_node *front, *rear;

        std::vector<vibe_node>  v_vibe_node;
        std::mutex node_lock;
}vibe_queue;

/*
parameter:
        width\height\chn\rate: Width, height, chnnal ,and frame rate of video stream images
        travel: Maximum time consumption of vibe detection algorithm
return:
        != NULL:   success
        == NULL:   failed      
*/
vibe_queue*jv_queue_init(int width, int height, int chn, int rate, int travel);

/*
parameter:
        head: queue head;
return:
        ==0 :   success
        < 0 :   failed      
*/
int jv_queue_exit( vibe_queue* queue_head );
/*
parameter:
        head: queue head;
        data: vibe detection algorithm data
return:
        ==0 :   success
        < 0 :   failed      
*/
int jv_queue_push_node_data(vibe_queue *head, vibe_data* data);
/*
parameter:
        head: queue head;
        mem: image buffer
        mem_size: image buffer space size
return:
        == 0:   success
        <  0:   failed      
*/
int jv_queue_pop_node_data(vibe_queue *head, unsigned char *mem, unsigned int mem_size);

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

#endif

queue.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>


#include "queue.h"

using namespace std;


static bool jv_queue_empty(vibe_queue *head)
{
        if ( head->front == NULL ) 
        {
                return true;
        }
        return false;
}
/*
parameter:
        width\height\chn\rate: Width, height, chnnal ,and frame rate of video stream images
        travel: Maximum time consumption of vibe detection algorithm
return:
        != NULL:   success
        == NULL:   failed      
*/
vibe_queue* jv_queue_init(int width, int height, int chn, int rate,int travel)
{
        if( width <0 || height <0 || chn<0 || rate < 0 || travel < 0 )
        {
                printf("queue init failed\n");
                return NULL;
        }
        
        vibe_queue* head;
        vibe_data node_data;
        vibe_node node;

        //1. create queue head
        head = (vibe_queue* )malloc(sizeof(vibe_queue));
        if(!head )
        {
                printf("queue create failed!...\n");
                return NULL;
        }
        head->front = NULL;
        head->rear = NULL;
        head->queue_len = ( ( travel * rate ) / 1000 +1) * 2;
        head->queue_index = 0;
        head->push_interval = 1000/rate;
        head->pop_interval = travel;

        head->info.rate = rate;
        head->info.height = height;
        head->info.width = width;
        head->info.chn = chn;
        
        //2. alloc mem pool
        memset(&node,0,sizeof(vibe_node));
        node_data.first = false;
        node_data.mem_size = chn*width*height;
        node_data.status = DATA_IDLE; 
        for(int i = 0; i < head->queue_len; i++)
        {
                node_data.mem = (unsigned char*)malloc( node_data.mem_size);
                memcpy(&node.data,&node_data,sizeof(vibe_data));
                head->v_vibe_node.push_back(node);
        }
        printf("success: queue create node = %ld!...\n",head->v_vibe_node.size());
        return head;
}
/*
parameter:
        head: queue head;
return:
        ==0 :   success
        < 0 :   failed      
*/
int jv_queue_exit( vibe_queue* head )
{
        //1. free queue head
         if (head == NULL) {
                return -1;
        }
        head->queue_len=0;
        head->queue_index=0;
        head->front = NULL;
        head->rear = NULL;
        free(head);
                
        //2. vibe node free image buffer and clean vector
        for(int i = 0; i < head->v_vibe_node.size(); i++)
        {
              if( head->v_vibe_node[i].data.mem)
              {
                free( head->v_vibe_node[i].data.mem);
              }
        }
        head->v_vibe_node.clear();
        return 0;
}

/*
parameter:
        head: queue head;
        data: vibe detection algorithm data
return:
        ==0 :   success
        < 0 :   failed      
*/
int jv_queue_push_node_data(vibe_queue *head, vibe_data* data)
{
        vibe_node *node = NULL;
        if ((head == NULL) || (data == NULL)) 
        {
                printf("Failed(%d): head or data is NULL\n",HEAD_DATA_NULL);
                return  HEAD_DATA_NULL;
        }

        if ( head->queue_index >= head->queue_len) 
        {
                printf("Failed(%d): queue full :queue_index=%d ,max =%d\n", QUEUE_FULL,head->queue_index ,head->queue_len);
                return QUEUE_FULL;
        }

        for(int i = 0; i < head->v_vibe_node.size();i++)
        {
                if( head->v_vibe_node[i].data.status == DATA_IDLE)
                {
                        node =  &head->v_vibe_node[i];
                        break;
                }
        }
        if(!node)
        {
                printf("Failed(%d): Not idle status node \n",NOT_IDLE);
                return NOT_IDLE;
        }

        if( data->mem_size != node->data.mem_size)
        {
                printf("Failed(%d): push data mem_size != node data mem_size\n",COPY_FAILED);
                return COPY_FAILED;
        }

        memcpy(node->data.mem, data->mem,node->data.mem_size);
        node->data.status = DATA_BUSY;
        node->next = NULL;

        if ( jv_queue_empty(head) == true) //first insert
        {
                head->front = node;
                head->rear = node;
        }
        else 
        {
                head->rear->next = node;
                head->rear = node;
        }
        head->queue_index++;
        return 0;
}

/*
parameter:
        head: queue head;
        mem: image buffer
        mem_size: image buffer space size
return:
        == 0:   success
        <  0:   failed      
*/
int jv_queue_pop_node_data(vibe_queue *head, unsigned char *mem, unsigned int mem_size)
{
        vibe_node *node = NULL;
        if ((head == NULL) || (head->front == NULL)) 
        {
               // printf("Failed(%d): queue is empty. \n",QUEUE_EMPTY);
                return QUEUE_EMPTY;
        }
       
        node = head->front;
        head->front = node->next;
        if (head->front == NULL) {
                head->rear = head->front;
        }
        head->queue_index--;
        
        if (mem_size != node->data.mem_size) 
        {
                printf("mem_size < node->data.mem_size=%d\n",mem_size);
                return -1;
        }
        head->node_lock.lock();
        memcpy(mem, node->data.mem, node->data.mem_size);
        node->data.status = DATA_IDLE;
        head->node_lock.unlock();
       
        return 0;
}

test.h

#ifndef TEST_H
#define TEST_H

#include "appThread.h"
#include "queue.h"

class Test: public AppThread
{
private:
   int m_type;
public:
    Test (int type){
        m_type = type;
    };
    ~Test(){};
   
protected:
    virtual void run(void * para=nullptr)override;
   
};

#endif

test.cpp

#include <iostream>
#include <unistd.h>
#include <signal.h>

#include "test.h"

using namespace std;

#define ROWS 5
#define COLS 5
unsigned char buff[ROWS][COLS];
unsigned char out[ROWS*COLS];
void print_buff()
{
    printf("----print buff-------\n");
    for(int i= 0; i<ROWS;i++){
        for(int j =0; j<COLS; j++)
        {
            printf("%03d,",buff[i][j]);
        }
        printf("\n");
    }
    printf("-----end------\n");
}
void print_out()
{
    printf("----print out-------\n");
    for(int i= 0; i<ROWS;i++){
        for(int j =0; j<COLS; j++)
        {
            printf("%03d,",out[i*COLS+j]);
        }
        printf("\n");
    }
    printf("-----end------\n");
}
void modify_buff(int val)
{
    for(int i= 0; i<ROWS;i++){
        for(int j =0; j<COLS; j++)
        {
            buff[i][j]=val;
        }
    }
}

static bool canExit = false;

bool getCanExitFlag(void){
    return canExit;
}

void sigroutine(int dunno){
    switch (dunno)
    {
    case SIGUSR1:
        printf("Get a signal -- SIGUSR1\n");
        canExit = true;
        break;
    case SIGINT:
        printf("Get a signal -- SIGINT\n");
        canExit = true;
        break;
    }
}
int main()
{
    vector<Test*> v_pop;
    //
    Test push1(0),*out;
    vibe_queue* head = jv_queue_init(COLS,ROWS,1,25,160);
    
    for(int i =0; i< head->queue_len/2;i++){
        out = new Test(1);
        v_pop.push_back(out);
    }
   
    for(int i =0; i< v_pop.size();i++){
        v_pop[i]->startThread(head);
    }
     push1.startThread(head);
    signal(SIGINT, sigroutine);
	signal(SIGUSR1, sigroutine);

    while(!getCanExitFlag()){
        usleep(100 * 1000);
    }
    push1.stop();
    for(int i =0; i< v_pop.size();i++){
        v_pop[i]->stop();
        delete v_pop[i];
        v_pop[i] = nullptr;
    }
    v_pop.clear();
    jv_queue_exit(head);
    cout<< "test success..." <<endl;
    return 0;
}

void Test::run(void *para)
{
    vibe_queue* q_head = (vibe_queue*)para;
    vibe_data vibe;
    vibe.mem = &buff[0][0];
    vibe.mem_size = ROWS*COLS;
    m_end = false;
    int a = 0;
    while (!m_end)
    {
        switch (this->m_type)
        {
        case 0/* constant-expression */:
            modify_buff(a++);
            if(jv_queue_push_node_data(q_head,&vibe)== SUCCESS){
                //print_buff();
            }
            usleep(q_head->push_interval * 1000);
            break;
        case 1:
            if(jv_queue_pop_node_data(q_head,out,ROWS*COLS) == SUCCESS){
                print_out();
                //Maximum simulation running time
                usleep(q_head->pop_interval *1000);
               
            }
           // 
            break;
        default:
            break;
        }
    }
    
}

appThread.h

#ifndef APP_THREAD_H
#define APP_THREAD_H

#include <stdio.h>
#include <functional>
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>

using namespace std;
#if 0
class MyThreadController {
public:
    MyThreadController()
        : _mutex( std::make_unique<std::mutex>()) 
        , _stop_condition(std::make_unique<std::condition_variable>()) {}

    ~MyThreadController() = default;

    void someFunctionThatNeedsSynchronization() {
        std::unique_lock<std::mutex> lock(*_mutex);
        // Critical section here...

        // Wait until notified
        _stop_condition->wait(lock, [this]{ return shouldStop; });
        // Lock is held again after wait

        // Critical section continues...
    }

    void signalToStop() {
        {
            std::lock_guard<std::mutex> lock(*_mutex);
            shouldStop = true;
        }
        _stop_condition->notify_all();
    }

private:
    std::unique_ptr<std::mutex> _mutex;
    std::unique_ptr<std::condition_variable> _stop_condition;
    bool shouldStop = false;
};
#endif
class AppThread
{
public:
    ~AppThread()
    {
        stopThread();
    };
    AppThread():m_end(true)
    {

    };

    //return 0:success -1:failed
    int startThread(void* para=nullptr)
    {
        if (!m_end)
        {
            return -1;
        }

        try
        {
            m_pthread = new std::thread(&AppThread::run, this,para);
        }
        catch (...)
        {
            throw "[Ower_Thread::start] thread start error";
        }
        return 0;
    };
    inline void stop(){m_end=true;}
protected:
    virtual void run(void * para=nullptr)=0;
    bool m_end;
    void stopThread()
    {
        m_end = true;
        
        if (m_pthread != nullptr) 
        { 
            // You need to ensure that the thread is finished before deleting it.
            if (m_pthread->joinable()) 
            {
                m_pthread->join();
            }
            delete m_pthread;
            m_pthread = nullptr;
        }    
    };
private:
    std::mutex *pMutexs;
    std::thread* m_pthread;
    std::mutex*  _mutex;
    std::condition_variable*  _stop_condition;
};

class AppTimer {
public:
    AppTimer(int interval, std::function<void()> callback)
        : _interval(interval), _callback(callback), _running(false) 
    {
        m_mutexs = new std::mutex();
    }
    ~AppTimer(){
        
    }
    void start() {
        _running = true;
        _thread = std::thread([this]() {
            while (_running) {
                std::this_thread::sleep_for(std::chrono::seconds(_interval));
                _callback();
            }
        });
    }
  
    void start_mil() {
        _running = true;
        _thread = std::thread([this]() {
            while (_running) {
                std::this_thread::sleep_for(std::chrono::milliseconds(_interval));
                _callback();
            }
        });
    }

    void stop() {
        _running = false;
        if (_thread.joinable()) {
            _thread.join();
        }
    }
    std::mutex *m_mutexs;
private:
    int _interval;
    std::function<void()> _callback;
    bool _running;
    std::thread _thread;
};
#endif

Makefile

.PHONY:all clean install

CXX := g++

CXX_SRC = $(shell find ./ -name "*.cpp")
OBJS = $(CXX_SRC:%.cpp=%.o) 

LDFLAGS:= -pthread

%.o:%.cpp
	$(CXX) -c $< -o $@ 

BIN=test	
build:$(OBJS)
	$(CXX) -o $(BIN) $(OBJS) $(LDFLAGS)

clean:
	rm -rf $(OBJS) $(BIN) 

-include $(OBJS:.o=.d)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ai_Sj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值