无锁队列--基于linuxkfifo实现

http://blog.csdn.net/wallwind/article/details/46504377

一直想写个无锁的队列,来提高项目后台的效率。

偶然看到Linux内核的kfifo.h 实现原理。于是自己仿照了这个实现,目前linux应该是可以对外提供接口了。

[cpp]  view plain  copy
  1. #ifndef _NO_LOCK_QUEUE_H_  
  2. #define _NO_LOCK_QUEUE_H_  
  3.   
  4. #include <stdlib.h>  
  5. #include <stdio.h>  
  6. #include <string.h>  
  7. #include <string>  
  8. #include <pthread.h>  
  9. #include <iostream>  
  10. using namespace  std;  
  11.   
  12. #ifndef max  
  13. #define max(x, y) ({                \  
  14.     typeof(x) _max1 = (x);          \  
  15.     typeof(y) _max2 = (y);          \  
  16.     (void) (&_max1 == &_max2);      \  
  17.     _max1 > _max2 ? _max1 : _max2; })  
  18. #endif  
  19.   
  20. #ifndef min  
  21. #define min(x, y) ({                \  
  22.     typeof(x) _min1 = (x);          \  
  23.     typeof(y) _min2 = (y);          \  
  24.     (void) (&_min1 == &_min2);      \  
  25.     _min1 < _min2 ? _min1 : _min2; })  
  26. #endif  
  27.   
  28. class Kfifo   
  29. {  
  30. public:  
  31.     Kfifo(unsigned int  isize);  
  32.     ~Kfifo();  
  33.     unsigned int get(unsigned char *buffer, unsigned int len);  
  34.     unsigned int put(const unsigned char *buffer, unsigned int len);  
  35.     static unsigned long roundup_power_of_two(unsigned long val);  
  36. private:  
  37.     inline bool is_power_of_2(unsigned long n)  
  38.     {  
  39.         return (n != 0 && ((n & (n - 1)) == 0));   
  40.     };  
  41.     inline unsigned int unused()  
  42.     {  
  43.         return (mask + 1) - (in - out);  
  44.     }  
  45.       
  46. private:  
  47.     unsigned int size;  
  48.     unsigned int in;   
  49.     unsigned int out;  
  50.     unsigned int    mask;  
  51.     unsigned char* buffer;  
  52. };  
  53.   
  54. struct proto  
  55. {  
  56.     unsigned int msgid;  
  57.     unsigned int cmd;  
  58.     unsigned int info;  
  59.     proto():msgid(0),cmd(0),info(0){}  
  60. };  
  61.   
  62. #endif  

实现文件

[cpp]  view plain  copy
  1. #include "MKfifo.h"  
  2.   
  3. Kfifo::~Kfifo()  
  4. {  
  5.     if (buffer) free(buffer);     
  6.     size = in = out=0;  
  7. }  
  8. unsigned long Kfifo::roundup_power_of_two(unsigned long val)  
  9. {  
  10.     if (val & (val-1) == 0)  
  11.     {  
  12.         return val;  
  13.     }  
  14.     unsigned long maxulong = (unsigned long )((unsigned long ) ~0);  
  15.     unsigned long andv = ~(maxulong&(maxulong>>1));  
  16.     while((andv & val) == 0)  
  17.     andv = andv>>1;  
  18.     return andv<<1;  
  19. }  
  20. Kfifo::Kfifo(unsigned int isize):size(isize),in(0),out(0),mask(size - 1)  
  21. {  
  22.     if (!is_power_of_2(isize))  
  23.     {  
  24.         size = roundup_power_of_two(isize);  
  25.     }  
  26.     buffer =(unsigned char*) malloc(isize);  
  27. }  
  28.   
  29. unsigned int Kfifo::get(unsigned char *_buffer, unsigned int len)  
  30. {  
  31.     unsigned int l;  
  32.     len = min(len, in - out);  
  33.     __sync_synchronize();  
  34.   
  35.     l = min(len,size -(out&(size-1)));  
  36.     memcpy(_buffer,buffer + (out& (size-1)),l);  
  37.     memcpy(_buffer + l,buffer,len - l);  
  38.   
  39.      __sync_synchronize();  
  40.   
  41.      out +=len;  
  42.      return len;  
  43.   
  44. }  
  45. unsigned int Kfifo::put(const unsigned char *_buffer, unsigned int len)  
  46. {  
  47.     unsigned int l;  
  48.     len = min(len, size - in + out);  
  49.      __sync_synchronize();  
  50.      l = min(len, size - (in & (size - 1)));  
  51.      memcpy(buffer + (in & (size - 1)), _buffer, l);  
  52.      memcpy(buffer, _buffer + l, len - l);  
  53.       __sync_synchronize();  
  54.        in += len;  
  55.        return len;  
  56.   
  57. }  
  58.   
  59. void * consumer(void * arg)  
  60. {  
  61.     printf("consumer\n");  
  62.     Kfifo* fifo = (Kfifo*) arg;  
  63.     if (!fifo)  
  64.     {  
  65.         return NULL;  
  66.     }  
  67.   
  68.     for (;;)  
  69.     {  
  70.         proto p;  
  71.         unsigned int len = fifo->get((unsigned char*)&p,sizeof(p));  
  72.         if (len>0)  
  73.         {  
  74.             cout << "~~~~~~~~~~~~~~~~~~~~"<<endl;  
  75.             cout << "consumer proto msg id :"<<p.msgid<<endl;  
  76.             cout << "consumer proto msg cmd :"<<p.cmd<<endl;  
  77.             cout << "consumer proto msg info :"<<p.info<<endl;  
  78.             cout << "~~~~~~~~~~~~~~~~~~~~"<<endl;  
  79.         }  
  80.     }  
  81.   
  82.       
  83.     return (void *)fifo;  
  84. }  
  85. void* producer(void* args)  
  86. {  
  87.     Kfifo* fifo = (Kfifo*) args;  
  88.       
  89.     if (!fifo)  
  90.     {  
  91.         return NULL;  
  92.     }  
  93.     unsigned int i=0;  
  94.     for (;;)  
  95.     {  
  96.         proto p;  
  97.         p.msgid = i++;  
  98.         p.cmd =  333;  
  99.         p.info = 44444;  
  100.         fifo->put((const unsigned char*)&p,sizeof(p));  
  101.         cout<<"producer put msgid :"<<p.msgid<<endl;  
  102.     }  
  103.     return (void*)fifo;  
  104. }  
  105. int main()  
  106. {  
  107.     Kfifo *fifo = new Kfifo(1024);  
  108.     pthread_t consumeid,producerid;  
  109.     pthread_create(&producerid,NULL,producer,(void*)fifo);  
  110.     pthread_create(&consumeid,NULL,consumer,(void*)fifo);  
  111.   
  112.     printf("info!!\n");  
  113.     pthread_join(consumeid,NULL);  
  114.     pthread_join(producerid,NULL);  
  115.     return 0;  
  116. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值