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;
}