Libfly协程库实现与原理——条件变量的实现


Libfly协程库简介:
libfly协程库,采用C++作为编程语言,封装了协程类,并提供了协程基本操作和调度功能
编写此协程库的目的是为了让协程理解起来更容易,让协程编程更加简单!
正逐步完善代码注释与文档,欢迎大家一起讨论交流~

Github地址:https://github.com/chudongfang/libfly


libfly协程库条件变量的实现

因为协程不会同时运行,所以不需要互斥锁,只需要条件变量
条件变量封装在 Conditional_variable 类中
wait() 函数等待条件变量
notify_one 唤醒一个等待协程
notify_all 唤醒所有等待协程
实现原理
其实现难点为如何唤醒协程, 这里我采用定时器,利用定时器的回调唤醒协程
这样一来  notify_one 和 notify_all 就可以轻松实现了
然后wait函数只需负责构造一个定时事件,存储需要唤醒的协程就好了
这个定时事件的时间需要非常短,这里我给了1秒.

class Conditional_variable
{

public:
    Conditional_variable();
    ~Conditional_variable();
    void wait();
    void notify_one();
    void notify_all();

public:
    std::queue<heap_timer*> routines_;
    int size_;     

};

wait()函数实现
对于每个等待条件变量的协程,条件变量都存储了一个存储协程指针的定时事件
以便于notify时把定时事件加入定时器,唤醒该协程.
当其存储了该协程信息后 , 其执行 yield() 退出本协程
void Conditional_variable::wait()
{
    Routine * curr_routine = get_curr_routine();
    heap_timer * cur_timer = new heap_timer(Cond_Callback , curr_routine , 1);     
    routines_.push(cur_timer);
    size_++;
    curr_routine->yield();
}

notify_one()函数实现
把一个存储在routines_中的定时事件唤醒即可,即把其加入定时器
void Conditional_variable::notify_one()
{
    if(routines_.empty()) 
        return ;

    heap_timer *cur_timer = routines_.front();
    get_curr_thread_env()->time_heap_->add_timer(cur_timer);
    routines_.pop();
    size_--;
}

notify_all()函数实现
把所有存储在routines_中的定时事件唤醒即可,即把其加入定时器

void Conditional_variable::notify_all()
{
    while(!routines_.empty())
    {
        heap_timer *cur_timer = routines_.front();
        get_curr_thread_env()->time_heap_->add_timer(cur_timer);
        routines_.pop();
    }
    size_ = 0;
}
条件变量使用实例
用一个例子了解其实现是最好的方式

这里给出了一个生产者-消费者模式,生产者一次生产三个,消费者一次消费一个.
这里 product 代表生产的产品.

下面给出协程切换过程
1. RoutineArr[1] resume 进入消费者协程
2. product 为 0 , 执行 wait() ,退出消费者协程,进入主协程
3. RoutineArr[2] resume 进入生产者协程
4. 生产者协程 notify_one 把唤醒消费者协程的事件加入定时器
5. poll等待,退出生产者协程,设置定时器在1秒后唤醒生产者协程
6. 进入主协程,主协程利用evenloop访问定时器,唤醒消费者协程
7. 消费者进行消费,并执行 wait() ,退出消费者协程,进入主协程
8. 主协程主协程利用evenloop访问poll参数的定时事件,唤醒生产者协程
//test for Conditional_variable


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <iostream>
#include "routine.h"
#include "routine.cpp"
#include <vector>
#include "Time_heap.h"
#include "Time_heap.cpp"
#include "Poller.h"
#include "Poller.cpp"
#include "Conditional_variable.cpp"
#include "Conditional_variable.h"

using namespace libfly;



Conditional_variable cond;
int product;


void *timerCallback(Routine * routine)
{
    //std::cout<<"I'm timerCallback Function. I will resume this routine!\n"<<std::endl;
    routine->resume();
}

void * Producer(void *arg)
{
    while(1)
    {
        product ++;
        product ++;
        product ++;
        std::cout<<"Producer  product::"<<product<<std::endl;
        cond.notify_one();

        //返回主协程
        Poller(timerCallback , get_curr_routine(),1); 

    }
}

void * Consumer(void *arg)
{
    while(1)
    {

        if(product == 0)
            cond.wait();
        product--;
        std::cout<<"Consumer  product::"<<product<<std::endl;
    }
}

int main()
{
    std::vector<Routine*> RoutineArr; 
    RoutineArr.push_back(new Routine(get_curr_thread_env(),NULL,Consumer,NULL) );   
    RoutineArr.push_back(new Routine(get_curr_thread_env(),NULL,Producer,NULL) );   
    for(int i=0;i<2;i++)
    {
        RoutineArr[i]->resume();
    }
    std::cout<<"I'm Main routine"<<std::endl; 
    EventLoop eventloop(get_curr_thread_env()->time_heap_,NULL,NULL);
    eventloop.loop();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值