Tecent libco C++协程库初探

安装

https://github.com/Tencent/libco 上把release版本的下下来:

mkdir build && cd build && cmake .. && make

拿到动态和静态库啦,然后cp到/usr/local/lib就完成安装啦。
项目有很多example,直接进根目录make就行了。

libco原理

主要是理解resume和yield,非常非常强烈建议的blog:
https://blog.didiyun.com/index.php/2018/11/23/libco/

使用单线程多协程实现生产者消费者

说明:这个例子里面没有加锁,大多数情况,单线程多协程无需加锁,但是有些情况需要,比如两个协程同时写一个文件。下面这个生产者消费者模型不需要加锁,因为它操作的共享变量是安全的,而在多线程模型下,调度是抢占的,由系统内核发起的,需要加锁,而协程是用户级别的模拟并发。协程的优势在于切换协程带来的花销远小于线程切换,线程切换需要陷入内核,切换寄存器和栈,协程则不需要。在多线程编码时,条件变量需要和锁一起用,而在协程编程中,不需要这种和锁搭配的条件变量,libco实现了一个条件变量stCoCond_t
使用libco步骤:

  1. 写协程函数 void*(*p)(void*),入口写co_enable_hook_sys();启用协程HOOK项。
  2. 声明协程 stCoRoutine_t
  3. 创建协程co_create(&pProducerCo, NULL, productor, &fac);
  4. 开启协程 co_resume(pProducerCo);
  5. 开启事件循环 co_eventloop(co_get_epoll_ct(), NULL, NULL);

编译下面这个demo:

g++ -o main main.cc -lcolib -lpthread -ldl -g

或者

g++ -o main -Wl,-Bstatic main.cc -lcolib -Wl,-Bdynamic -lpthread -ldl -g 

由于我lib目录下有同名的libco静态和动态库,g++会默认使用动态库,如果想用静态库编译,使用第二个编译命令。另外 -ldl是必须的,貌似colib内部会加载一些基础动态库。

#include "co_routine.h"
#include 
#include 
#include 
// g++优先使用同名动态库 
// g++ -o main main.cc -lcolib -lpthread -ldl -g
// 使用同名静态库编译
// g++ -o main -Wl,-Bstatic main.cc -lcolib -Wl,-Bdynamic -lpthread -ldl -g 

int task = 0;
using namespace std;
class Factory {
public:
    Factory() {
        maxElement_ = 5;
        proCond_ = co_cond_alloc();
        conCond_ = co_cond_alloc();
    }
    stCoCond_t* proCond_;
    stCoCond_t* conCond_;
    queue<int> taskQ_;
    int maxElement_;
};

void* productor(void* arg) {
    // 启用协程HOOK项
    co_enable_hook_sys();
    Factory* fac = static_cast<Factory*>(arg);
    while (true) {
        while (fac->taskQ_.size() >= fac->maxElement_) {
            co_cond_timedwait(fac->proCond_, -1);
        }
        fac->taskQ_.push(task++);
        cout << "生产任务:" <<  fac->taskQ_.back() << endl;
        co_cond_signal(fac->conCond_);
    }
}

void* consumer(void* arg) {
    // 启用协程HOOK项
    co_enable_hook_sys();
    Factory* fac = static_cast<Factory*>(arg);
    while (true) {
        while (fac->taskQ_.empty()) {
            co_cond_timedwait(fac->conCond_, -1);
        }
        int task = fac->taskQ_.front();
        fac->taskQ_.pop();
        cout << "消费任务:" <<  task << endl;
        co_cond_signal(fac->proCond_);
    }
}

int main(int argc, char** argv) {
    const int nConsumer = 2;
    stCoRoutine_t* pProducerCo = NULL;
    stCoRoutine_t* pConsumerCo[nConsumer] = { NULL };
    Factory fac;
    // 创建启动生产者协程
    // 看源码可知该函数必返回0
    co_create(&pProducerCo, NULL, productor, &fac);
    co_resume(pProducerCo);
    cout << "start producer coroutine success" << endl;

    // 创建启动消费者协程
    for (int i = 0; i < nConsumer; i++)
    {
        co_create(&pConsumerCo[i], NULL, consumer, &fac);
        co_resume(pConsumerCo[i]);
    }
    cout << "start consumer coroutine success" << endl;
    // 启动循环事件
    co_eventloop(co_get_epoll_ct(), NULL, NULL);
    return 0;
}
消费任务:41253
消费任务:41254
生产任务:41255
生产任务:41256
生产任务:41257
生产任务:41258
生产任务:41259
消费任务:41255
消费任务:41256
消费任务:41257
消费任务:41258
消费任务:41259
生产任务:41260
生产任务:41261
生产任务:41262
生产任务:41263
生产任务:41264
消费任务:41260
消费任务:41261
消费任务:41262
消费任务:41263
消费任务:41264
生产任务:41265
生产任务:41266
生产任务:41267
生产任务:41268
生产任务:41269
消费任务:41265

Tecent libco C++协程库初探_第1张图片
只有一个线程,佐证了协程的含义。

你可能感兴趣的:(C++,多线程编程,Linux,c++,开发语言,算法)