队列push/pop
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0d62b3aab877410cbefd90a9e19912c4.jpeg)
queue.h
#ifndef _QUEUE_H__
#define _QUEUE_H__
#include <vector>
#include <mutex>
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif
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;
int pop_interval;
img_info info;
vibe_node *front, *rear;
std::vector<vibe_node> v_vibe_node;
std::mutex node_lock;
}vibe_queue;
vibe_queue*jv_queue_init(int width, int height, int chn, int rate, int travel);
int jv_queue_exit( vibe_queue* queue_head );
int jv_queue_push_node_data(vibe_queue *head, vibe_data* data);
int jv_queue_pop_node_data(vibe_queue *head, unsigned char *mem, unsigned int mem_size);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#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;
}
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;
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;
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;
}
int jv_queue_exit( vibe_queue* head )
{
if (head == NULL) {
return -1;
}
head->queue_len=0;
head->queue_index=0;
head->front = NULL;
head->rear = NULL;
free(head);
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;
}
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)
{
head->front = node;
head->rear = node;
}
else
{
head->rear->next = node;
head->rear = node;
}
head->queue_index++;
return 0;
}
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))
{
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:
modify_buff(a++);
if(jv_queue_push_node_data(q_head,&vibe)== SUCCESS){
}
usleep(q_head->push_interval * 1000);
break;
case 1:
if(jv_queue_pop_node_data(q_head,out,ROWS*COLS) == SUCCESS){
print_out();
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);
_stop_condition->wait(lock, [this]{ return shouldStop; });
}
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)
{
};
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)
{
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)