基于无锁队列和c++11的高性能线程池
线程使用c++11库
和线程池之间的消息通讯使用一个简单的无锁消息队列
适用于linux平台,gcc 4.6以上

 
标签: <无>
 

代码片段(6)[全屏查看所有代码]

1. [代码]lckfree.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// lckfree.h
// Implementation of lock free queue using CAS operations
// for simple multi-threading use cases like:
// 1. multiple worker to process incoming messages
// 2. async processing using a thread pool
// 3. simple tcp server deal with async requests
// Author: typhoon_1986@163.com
// Refrence: http://coolshell.cn/articles/8239.html
 
#ifndef __LCKFREE_H__
#define __LCKFREE_H__
 
#include <string>
using namespace std;
 
namespace bfd {
 
struct LinkNode {
  string data;
  LinkNode* next;
};
typedef struct LinkNode LinkNode;
 
class LckFreeQueue {
 public:
  LckFreeQueue();
  ~LckFreeQueue();
 
  int push(const string &msg);
  string pop();  // non-block pop method
//  string bpop(); // block pop method
  bool empty();
 private:
  LinkNode * head_;
  LinkNode * tail_;
  bool empty_;
  unsigned int length_;
};
 
} // namespace bfd
#endif

2. [代码]lckfree.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <lckfree.h>
 
namespace bfd {
 
LckFreeQueue::LckFreeQueue(): head_(NULL), tail_(NULL), empty_(true), length_(0) {
  head_ = new LinkNode;
  head_->next = NULL;
  tail_ = head_;
}
 
LckFreeQueue::~LckFreeQueue() {
  LinkNode *p = head_;
  if (p) {
    LinkNode *q = p->next;
    delete p;
    p = q;
  }
}
 
int LckFreeQueue::push(const string &msg) {
  LinkNode * q = new LinkNode;
  q->data = msg;
  q->next = NULL;
 
  LinkNode * p = tail_;
  LinkNode * oldp = p;
  do {
    while (p->next != NULL)
        p = p->next;
  } while( __sync_bool_compare_and_swap(&(p->next), NULL, q) != true); //如果没有把结点链在尾上,再试
 
  __sync_bool_compare_and_swap(&tail_, oldp, q); //置尾结点
  return 0;
}
 
string LckFreeQueue::pop() {
  LinkNode * p;
  do{
    p = head_;
    if (p->next == NULL){
      return "";
    }
  } while( __sync_bool_compare_and_swap(&head_, p, p->next) != true );
  return p->next->data;
}
 
bool LckFreeQueue::empty() {
  return empty_;
}
 
}

3. [代码]workthreadpool.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// workthreadpool.h
// 一个用于将消息分发给多个进程,并使用多个进程处理的库,工作进程并不返回数据
#ifndef __WORK_THREAD_POOL__
#define __WORK_THREAD_POOL__
 
#include <stdio.h>
#include <thread>
#include <queue>
#include <string>
#include <vector>
#include "lckfree.h"
 
using namespace std;
namespace bfd {
 
class WorkThreadPool {
 public:
  WorkThreadPool(int size);
  virtual ~WorkThreadPool();
 
  // 需要子类继承并实现的函数,每个线程实际执行的内容
  virtual void Init() {};
  virtual void Finish() {};
  virtual void Handle(const string &msg)=0;
 
  // 将消息放入处理队列, 消息只支持string类型
  int SendMessage(const string &msg);
 
  int Start();
  int Stop();
 
 private:
  void Worker();
 
  int size_;
  LckFreeQueue msg_queue_; // 线程池的协作基于这个无锁队列
  vector<thread> thread_pool_;
};
} // namespace
#endif

4. [代码]workthreadpool.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "workthreadpool.h"
#include <sstream>
#include <unistd.h>
 
namespace bfd {
WorkThreadPool::WorkThreadPool(int size) {
  if (size <= 0) { // 最小也需要有1个线程
    size_ = 1;
  } else {
    size_ = size;
  }
}
 
WorkThreadPool::~WorkThreadPool() {
 
}
 
int WorkThreadPool::SendMessage(const string &msg) {
  msg_queue_.push(msg);
  return 0;
}
 
void WorkThreadPool::Worker() {
  unsigned int msg_count = 0;
  while (1) {
    string msg = msg_queue_.pop();
    if (msg.empty()) {
      printf("no msg got, sleep for 0.1 sec\n");
      usleep(100000); // 0.1 sec
      continue;
    }
 
    if (msg == "__exit__") {
      stringstream ss;
      ss << "exit worker: " << std::this_thread::get_id() << ", processed: " << msg_count << "..";
      printf("%s\n", ss.str().c_str());
      return;
    }
    Handle(msg);
    msg_count++;
    if (msg_count % 1000 == 0) {
      printf("every 1000 msg count\n");
    }
  }
}
 
int WorkThreadPool::Start() {
  for (int i=0; i < size_; i++) {
    thread_pool_.push_back( thread(&WorkThreadPool::Worker, this) );
  }
  return 0;
}
 
int WorkThreadPool::Stop() {
  for (int i=0; i < size_; i++) {
    SendMessage("__exit__");
  }
  for (int i=0; i < size_; i++) {
    thread_pool_[i].join();
  }
  return 0;
}
 
}

5. [代码]main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "workthreadpool.h"
#include <sstream>
#include <math.h>
 
class MyThreadPool : public bfd::WorkThreadPool {
 public:
  MyThreadPool(int size) : bfd::WorkThreadPool(size) {
  }
  void Handle(const string &msg) {
    stringstream ss;
    ss << "worker (" << std::this_thread::get_id() << ") got msg: " << msg;
    printf("%s\n", ss.str().c_str());
    for (int i=0; i<=999999; i++) {
      double result = sqrt(sqrt(i) / 93.234);
    }
  }
};
 
int main() {
  printf("start running ....\n");
  MyThreadPool pool(5);
  pool.Start();
  for (int i=0; i<100; i++) {
    pool.SendMessage("msg info ----------");
  }
  pool.Stop();
 
  return 0;
}

6. [代码]Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LIB_SRC_FILES = src/workthreadpool.cpp src/lckfree.cpp
TEST_SRC_FILES = src/main.cpp
INCLUDE_DIR = src
STD_FLAG = -std=c++0x
 
all: main.o libs
    g++ $(STD_FLAG) -o test_workthreadpool main.o libworkthreadpool.so -lpthread
     
main.o: $(TEST_SRC_FILES)
    g++ $(STD_FLAG) -c $(TEST_SRC_FILES) -I$(INCLUDE_DIR)
 
libs: $(LIB_SRC_FILES)
    g++ $(STD_FLAG) -o libworkthreadpool.so -fPIC -O2 -shared -Wl,--no-as-needed -Isrc $(LIB_SRC_FILES) -lpthread
 
.PHONY : clean
clean :
    rm -f test_workthreadpool main.o libworkthreadpool.so

基于无锁队列和c++11的高性能线程池的更多相关文章

  1. Erlang运行时中的无锁队列及其在异步线程中的应用

    本文首先介绍 Erlang 运行时中需要使用无锁队列的场合,然后介绍无锁队列的基本原理及会遇到的问题,接下来介绍 Erlang 运行时中如何通过“线程进度”机制解决无锁队列的问题,并介绍 Erlang ...

  2. 无锁队列--基于linuxkfifo实现

    一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...

  3. 基于folly的AtomicIntrusiveLinkedList无锁队列进行简单封装的多生产多消费模型

    1.基于folly的AtomicIntrusiveLinkedList略微修改的无锁队列代码: #ifndef FOLLY_REVISE_H #define FOLLY_REVISE_H namesp ...

  4. 【DPDK】【ring】从DPDK的ring来看无锁队列的实现

    [前言] 队列是众多数据结构中最常见的一种之一.曾经有人和我说过这么一句话,叫做“程序等于数据结构+算法”.因此在设计模块.写代码时,队列常常作为一个很常见的结构出现在模块设计中.DPDK不仅是一个加 ...

  5. 无锁队列以及ABA问题

    队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...

  6. boost 无锁队列

    一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...

  7. 一个可无限伸缩且无ABA问题的无锁队列

    关于无锁队列,详细的介绍请参考陈硕先生的<无锁队列的实现>一文.然进一步,如何实现一个不限node数目即能够无限伸缩的无锁队列,即是本文的要旨. 无锁队列有两种实现形式,分别是数组与链表. ...

  8. folly无锁队列,尝试添加新的函数(续)

    基于上一篇文章,dropHead取出节点后,删除节点,会出现内存访问的问题.按照这个逻辑,如果将移出的节点保存到一个无锁队列中,然后在需要节点的时候,从这个备用的无锁队列中取出节点,那么应该就可以避开 ...

  9. DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

    [概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天 ...

随机推荐

  1. Unity查找子物体的方式-怎么查找GameObject

    Unity动态查找物体 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心创 ...

  2. Sublime Text3:插件+快捷键+环境变量设置+C/C++编译环境

    环境变量配置 如果电脑里之前下载过Codeblocks或者Dev,找到文件根目录,打开MinGw(或者MinGw64),点开bin目录,将bin文件夹的目录复制下来(以Codeblocks为例,将文件 ...

  3. HPU1460: 杨八方的表面兄弟

    题目描述 如果你之前关注过HPUOJ的话,那么你一定听说过杨八方的名字.在去年,很多同学共同见证了杨八方同学的填报志愿.来到学校.军训--或许你曾陪同杨八方一起思考过许多问题,又或者你是刚听说这个名字 ...

  4. 数据库(linux)

    基本指令整合: 删除数据库 drop table   department 修改表中已有记录 update  company  set    salary=3000 where   age-25: u ...

  5. 2017.4.4 TCP/IP协议栈

    OSI和TCP/IP的各层协议总结: TCP/IP在封装和传输数据时,各层所做的工作:

  6. django HttpResponse的用法

    一.传json字典 def back_json(rquest): #JsonResponse父类是HttpResponse,原码里调用了json.dumps() from django.http im ...

  7. python------模块定义、导入、优化 ------->re模块

    该部分内容引用自:http://www.cnblogs.com/alex3714/articles/5161349.html 谢谢原博主的文章,只是自己学习,无其他使用. re模块 常用正则表达式符号 ...

  8. 【BZOJ4720】【NOIP2016】换教室

    我当年真是naive…… 原题: 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节 课程安排在n个时间段上.在第i(1≤i≤n)个时间段上,两节 ...

  9. 【SpringCloud】初识springCloud

    转载来源:https://maimai.cn/article/detail?fid=1149221357&efid=lL_Z3WzTyUDLAjQwrNrIsw 概述 毫无疑问,Spring ...

  10. LG4781 【模板】拉格朗日插值

    题意 题目描述 由小学知识可知,$n$个点$(x_i,y_i)$可以唯一地确定一个多项式 现在,给定$n$个点,请你确定这个多项式,并将$k$代入求值 求出的值对$998244353$取模 输入输出格 ...