在多线程编程中经常需要进行线程与线程间的通信,由于线程间能够共享数据结构,也就是一个全局变量能够被两个线程同时候使用。但是要注意的是线程的同步和互斥。
线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
线程互斥是指当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。一般采用互斥锁来解决互斥的问题,但是使用时一定要注意避免死锁。
在接收回调数据的时候,不能进行太过耗时的处理,通常将数据拷贝至消息队列,在其他线程进行处理。如下为项目总结的消息队列和使用示例:
msg_process.c
#include
#include
#include
#include "msg_process.h"
#define LOG_ERR(fmt, ...) do{\
printf("[ERROR] "fmt" [line:%d] [%s]\n", ##__VA_ARGS__, __LINE__, __FUNCTION__);\
}while(0);
static unsigned long timeout_ns = 0;
/**
* 消息处理模块内部接口
*/
static void put_msg_to_buffer(tmsg_buffer* buf, tmsg_element* elm){
if (NULL == buf || NULL == elm) {
return;
}
if (NULL != elm->next) {
elm->next = NULL;
}
pthread_mutex_lock(&buf->mutex);
//缓冲区中无消息节点
if (0 == buf->num) {
gettimeofday(&timenow,NULL);
timeout.tv_sec = timenow.tv_sec + block/1000; //加上秒数
block %= 1000; //得到毫秒数
timeout_ns = timenow.tv_usec*1000 + block*1000*1000;
if( timeout_ns >= 1000*1000*1000 ) //若超过1s
{
timeout.tv_sec ++;
timeout.tv_nsec = timeout_ns - 1000*1000*1000;
}
else
timeout.tv_nsec = timeout_ns;
//带超时时间阻塞线程等待消息节点
pthread_cond_timedwait(&buf->not_empty, &buf->mutex, &timeout);
}
pthread_mutex_unlock(&buf->mutex);
}
static tmsg_element* get_msg_from_buffer(tmsg_buffer* buf, int block){
tmsg_element *elm = NULL;
if (NULL == buf) {
return NULL;
}
pthread_mutex_lock(&buf->mutex);
//缓冲区中无消息节点
while (0 == buf->num) {
//阻塞线程等待消息节点
pthread_cond_wait(&buf->not_empty, &buf->mutex);
}
//从缓冲区首部取出消息节点
elm = buf->first;
if (1 == buf->num) {
buf->first = buf->last = NULL;
buf->num = 0;
} else {
buf->first = buf->first->next;
buf->num --;
}
pthread_mutex_unlock(&buf->mutex);
return elm;
}
static tmsg_element* get_msg_from_buffer_timeout(tmsg_buffer* buf, int block/*ms*/){
tmsg_element *elm = NULL;
struct timeval timenow;
struct timespec timeout;
if (NULL == buf) {
return NULL;
}
pthread_mutex_lock(&buf->mutex);
//缓冲区中无消息节点
if (0 == buf->num) {
gettimeofday(&timenow);
timeout.tv_sec = timenow.tv_sec;
timeout.tv_nsec = (timenow.tv_usec + block * 1000) * 1000;
//带超时时间阻塞线程等待消息节点
pthread_cond_timedwait(&buf->not_empty, &buf->mutex, &timeout);
}
if (buf->num > 0) {
//从缓冲区首部取出消息节点
elm = buf->first;
if (1 == buf->num) {
buf->first = buf->last = NULL;
buf->num = 0;
} else {
buf->first = buf->first->next;
buf->num --;
}
}
pthread_mutex_unlock(&buf->mutex);
return elm;
}
static tmsg_element* clear_msg_buffer(tmsg_buffer* buf){
tmsg_element* elm = NULL;
tmsg_element* elm_tmp = NULL;
if (NULL == buf){
return NULL;
}
//清空buffer中当前消息节点之前的所有消息节点
pthread_mutex_lock(&buf->mutex);
if (buf->num > 0) {
elm = buf->first;
while(elm != NULL) {
//首尾指针指向同一消息节点
if (elm == buf->last) {
buf->first = buf->last;
if (buf->num != 1) {
buf->num = 1;
}
break;
}
elm_tmp = elm->next;
free_tmsg_element(elm);
buf->num --;
elm = elm_tmp;
buf->first = elm;
}
}
pthread_mutex_unlock(&buf->mutex);
return elm;
}
static void send_msg_to_buffer(tmsg_buffer* buf, int msg, int ext, char* str, int len)
{
tmsg_element *elm = NULL;
elm = (tmsg_element *)malloc(sizeof(tmsg_element));
if (NULL == elm) {
LOG_ERR("new msg element failed!!");
return;
}
//填充消息节点数据
memset(elm, 0, sizeof(tmsg_element));
elm->msg = msg;
elm->ext = ext;
elm->dt = NULL;
elm->dt_len = len;
if (str)
{
elm->dt = (char *)malloc(len); //根据发送的大小申请内存
memmove(elm->dt, str, len);
}
elm->next = NULL;
//将消息节点添加到缓冲区中
put_msg_to_buffer(buf, elm);
}
static void send_msg_to_buffer_ex(tmsg_buffer* buf, int msg, int ext, int sub0, int sub1, char* str, int len){
tmsg_element *elm = NULL;
elm = (tmsg_element *)malloc(sizeof(tmsg_element));
if (NULL == elm) {
LOG_ERR("new msg element failed!!");
return;
}
//填充消息节点数据
memset(elm, 0, sizeof(tmsg_element));
elm->msg = msg;
elm->ext = ext;
elm->sub0 = sub0;
elm->sub1 = sub1;
elm->dt = NULL;
elm->dt_len = len;
if (str)
{
elm->dt = (char *)malloc(len); //根据发送的大小申请内存
memmove(elm->dt, str, len);
}
elm->next = NULL;
//将消息节点添加到缓冲区中
put_msg_to_buffer(buf, elm);
}
static void dispose_msg_buffer(tmsg_buffer* buf){
tmsg_element* elm = NULL;
if (NULL == buf) {
return;
}
if (buf->first != buf->last
&& buf->num > 0) {
elm = clear_msg_buffer(buf);
} else {
elm = buf->last;
}
if (NULL != elm) {
free_tmsg_element(elm);
buf->first = buf->last = NULL;
buf->num = 0;
}
pthread_mutex_destroy(&buf->mutex);
pthread_cond_destroy(&buf->not_empty);
free(buf);
buf = NULL;
}
static int get_msg_num(tmsg_buffer* buf){
if (NULL == buf) {
return 0;
}
return buf->num;
}
/**
* 以下为消息处理模块对外接口
*/
/*消息缓冲区初始化*/
tmsg_buffer* msg_buffer_init(void){
tmsg_buffer* msg_buffer = NULL;
msg_buffer = (tmsg_buffer *)malloc(sizeof(tmsg_buffer));
if (NULL == msg_buffer){
LOG_ERR("init msg buffer failed!!");
return NULL;
}
//初始化成员变量和函数
memset(msg_buffer, 0, sizeof(tmsg_buffer));
msg_buffer->first = NULL;
msg_buffer->last = NULL;
msg_buffer->num = 0;
pthread_mutex_init(&(msg_buffer->mutex), NULL);
pthread_cond_init(&(msg_buffer->not_empty), NULL);
//继续绑定接口
msg_buffer->put = put_msg_to_buffer;
msg_buffer->get = get_msg_from_buffer;
msg_buffer->get_timeout = get_msg_from_buffer_timeout;
msg_buffer->clear = clear_msg_buffer;
msg_buffer->sendmsg = send_msg_to_buffer;
msg_buffer->sendmsgex = send_msg_to_buffer_ex;
msg_buffer->dispose = dispose_msg_buffer;
msg_buffer->getnum = get_msg_num;
return msg_buffer;
}
/*复制消息节点*/
tmsg_element* dup_msg_element(tmsg_element* elm){
tmsg_element* msg_element = NULL;
if (NULL == elm) {
LOG_ERR("msg element is NULL!!");
return NULL;
}
msg_element = (tmsg_element *)malloc(sizeof(tmsg_element));
if (NULL == msg_element) {
LOG_ERR("create msg element is failed!!");
return NULL;
}
memcpy(msg_element, elm, sizeof(tmsg_element));
return msg_element;
}
void free_tmsg_element(tmsg_element *msg_element)
{
if(msg_element != NULL)
{
if(msg_element->dt != NULL)
{
free(msg_element->dt);
msg_element->dt = NULL;
}
free(msg_element);
msg_element = NULL;
}
}
msg_process.h
#ifndef _MSG_PROCESS_H_
#define _MSG_PROCESS_H_
#include
typedef struct msg_element tmsg_element;
struct msg_element
{
tmsg_element* next;
int msg;
int ext;
int sub0;
int sub1;
int dt_len;
char *dt;
};
typedef struct msg_buffer tmsg_buffer;
struct msg_buffer
{
tmsg_element* first;
tmsg_element* last;
int num;
pthread_mutex_t mutex;
pthread_cond_t not_empty;
void (*put)(tmsg_buffer* buf, tmsg_element* elm);
tmsg_element* (*get)(tmsg_buffer* buf, int block);
tmsg_element* (*get_timeout)(tmsg_buffer* buf, int block);
tmsg_element* (*clear)(tmsg_buffer* buf);
void (*sendmsg)(tmsg_buffer* buf, int msg, int ext, char* str, int len);
void (*sendmsgex)(tmsg_buffer* buf, int msg, int ext, int sub0, int sub1, char* str, int len);
void (*dispose)(tmsg_buffer* buf);
int (*getnum)(tmsg_buffer* buf) ;
};
/*消息缓冲区初始化*/
tmsg_buffer* msg_buffer_init(void);
/*复制消息节点*/
tmsg_element* dup_msg_element(tmsg_element* elm);
/*释放消息节点*/
void free_tmsg_element(tmsg_element *msg_element);
#endif /* MESSAGE_MSG_CENTER_H_ */
example.c //调用示例
#include
#include "msg_process.h"
int main(int argc,char *argv[])
{
tmsg_buffer* test_msg_buff = NULL;
test_msg_buff = msg_buffer_init();
char table[] = "{\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\","
"\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\""
",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\""
",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\""
",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\",\"hello\",\"world\"}";
test_msg_buff->sendmsg(test_msg_buff,0,0,table,sizeof(table)); //发送数据
sleep(2);
tmsg_element* event = NULL;
event = test_msg_buff->get_timeout(test_msg_buff,1000); //接收数据
if(event != NULL)
{
if(event->dt != NULL)
{
int i = 0;
printf("Recv:");
for(i=0; idt_len; i++)
{
printf("%c",event->dt[i]);
}
printf("\n");
}
}
free_tmsg_element(event);
return 0;
}
执行结果: