基于无锁队列和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的高性能线程池的更多相关文章
- Erlang运行时中的无锁队列及其在异步线程中的应用
本文首先介绍 Erlang 运行时中需要使用无锁队列的场合,然后介绍无锁队列的基本原理及会遇到的问题,接下来介绍 Erlang 运行时中如何通过“线程进度”机制解决无锁队列的问题,并介绍 Erlang ...
- 无锁队列--基于linuxkfifo实现
一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...
- 基于folly的AtomicIntrusiveLinkedList无锁队列进行简单封装的多生产多消费模型
1.基于folly的AtomicIntrusiveLinkedList略微修改的无锁队列代码: #ifndef FOLLY_REVISE_H #define FOLLY_REVISE_H namesp ...
- 【DPDK】【ring】从DPDK的ring来看无锁队列的实现
[前言] 队列是众多数据结构中最常见的一种之一.曾经有人和我说过这么一句话,叫做“程序等于数据结构+算法”.因此在设计模块.写代码时,队列常常作为一个很常见的结构出现在模块设计中.DPDK不仅是一个加 ...
- 无锁队列以及ABA问题
队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...
- boost 无锁队列
一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...
- 一个可无限伸缩且无ABA问题的无锁队列
关于无锁队列,详细的介绍请参考陈硕先生的<无锁队列的实现>一文.然进一步,如何实现一个不限node数目即能够无限伸缩的无锁队列,即是本文的要旨. 无锁队列有两种实现形式,分别是数组与链表. ...
- folly无锁队列,尝试添加新的函数(续)
基于上一篇文章,dropHead取出节点后,删除节点,会出现内存访问的问题.按照这个逻辑,如果将移出的节点保存到一个无锁队列中,然后在需要节点的时候,从这个备用的无锁队列中取出节点,那么应该就可以避开 ...
- DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了
[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天 ...
随机推荐
- git 应用
git - 简易指南 助你开始使用 git 的简易指南,木有高深内容,;). 安装 下载 git OSX 版 下载 git Windows 版 下载 git Linux 版 创建新仓库 创建新文件夹, ...
- lnmp架构、mysql的安装、php的安装、nginx相关
1.lnmp架构 2.mysql的安装: mysql5.6自动安装脚本: yum install perl-Data-Dumper.x86_64 libaio.x86_64 libaio-devel. ...
- 博客 first
2016.10.28 这会是一个值得纪念的日子,我将会从此刻开始,1~2天不间断的更新我再软件,编程方面的学习历程和在大学的琐事. 希望N年后看到,能够回味. a good memery....... ...
- oracle 日常
oracle sql server select 1 from dual 和 select 1 nvl(null,0) 为空显示 0 greatest (1, 3, 2 ) ...
- pageContext中page、request、session、application四种范围变量的用法。
在PageContext中有很多作用域 第一种:PageContext.PAGE_SCOPE适用于当前页面的作用域,其接受数据的代码是pageContext.getAttribute();访问页面也是 ...
- 【shell编程】之基础知识-常用命令
一.Shell echo命令 Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出.命令格式: echo string 您可以使用echo实现更复杂的输出格式控制. ...
- CH4912 Meteors
题意 4912 Meteors 0x49「数据结构进阶」练习 描述 Byteotian Interstellar Union有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第 ...
- Linux内核模块编程之Helloworld(初级)
注意printk那里,KERN_ALERT和打印消息之间是没有逗号的,搞得劳资查了半天才发现一直没有提示信息的原因 #include <linux/init.h> #include < ...
- 使用kompose 快速转换dokcer-compose 文件为k8s deploy 文件
kompose 是一个不错的快速转换docker-compose 文件为k8s 部署yaml文件的工具,使用次工具我们 可以将简单的docker-compose文件,转换为复杂的yaml文件,对于使用 ...
- JavaScript Closures 闭包
在一些编程语言中, 当我们执行完成function中的局部代码仅在函数执行期间可运行. 但是JS 事不一样的 闭包总结来说, 就是innerFunction 总是有使用outer function 的 ...