之前在设计消息队列的时候,用的双缓冲,保持一个读线程,一个写线程!! 读线程对read_list进行操作,写线程对write_list进行操作,保持一个队列的完整行就ok!
比如如果想保持write_list一致,就是在插入操作的时候枷锁,在read_list为空的时候需要和write_list进行交换,也需要枷锁!!这样就保证了很少的线程冲突!!!当时的消息队列的双缓冲使用std::list进行设计!
第二个版本的消息队列,进行了很大程度上的改进,使用了三个缓冲队列,一个读队列,一个写队列,一个缓冲队列,三个队列分别用数组形式体现,枷锁只要保证缓冲队列一致既可,即写队列向缓冲队列提交数据的时候,需要枷锁,读队列再向缓冲队列交换数据的时候,需要枷锁!想比较于上面的方法,枷锁次数明显减少,并且使用数组的形式,较std::list更为高效!这个消息队列在原公司的双缓冲队列的基础之上,进行设计!
给出测试代码!和部分接口!
DuplexList _List;void* producer(void* args){ int i=0; while(1) { int* j = new int(); *j = i; _List.append(j); usleep(0); i++; if(i % 100 == 0) { usleep(100); } } return (void*)0;}int main(){ pthread_t pid; pthread_create(&pid,NULL,producer,NULL); long long int start = get_os_system_time(); int old=-1; while(true) { int* j = 0; _List.peek((void* &)j); if(j != 0) { usleep(0); if(*j != old + 1) { printf("error!\n"); } old = *j; delete j; } } return 0;}
接口:
class DuplexList{public: DuplexList(int size = 1024); virtual ~DuplexList(void); virtual int append(CommonItem item); virtual int peek(CommonItem &item);protected: virtual int swap(CommonItem &item); virtual int submit();protected: CommonList *read_list_; CommonList *share_list_; CommonList *write_list_; Mutex _switch_mutex; int peek_index_;};
做了一下午的测试,没有问题,传递10w条消息大概使用20ms左右!这个性能可以了!
之前在语言的选择上面做了很长时间的犹豫,一些java的朋友劝我说,一个消息队列的错误,那么整个游戏就会崩溃!劝我使用java的集成结构!! 不过最终我还是坚持了C++,底层代码使用C++,逻辑使用lua来编写!只是在AI的问题上面还有很多犹豫!