co_routine.h
#ifndef __CO_ROUTINE_H__
#define __CO_ROUTINE_H__
#include <stdint.h>
#include <sys/poll.h>
#include <pthread.h>
//1.struct
struct stCoRoutine_t;//协程的结构体 用来存储协程相关的信息 具体含义会在 co_routine.cpp 给出
struct stShareStack_t;//共享栈结构体 存储共享栈相关信息 具体信息会在 co_routine_inner.h 给出
struct stCoRoutineAttr_t // 用来初始化共享栈时使用的结构体。
{
int stack_size; //栈的大小
stShareStack_t* share_stack; //分配的共享栈
stCoRoutineAttr_t()//默认构造函数
{
stack_size = 128 * 1024;
share_stack = NULL;
}
}__attribute__ ((packed));
/*
__attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节
数进行对齐,是GCC特有的语法。(http://blog.chinaunix.net/uid-25768133-id-3485479.html)
*/
struct stCoEpoll_t;//控制定时的结构体 用来管理时间请求
typedef int (*pfn_co_eventloop_t)(void *); //定义一个函数指针 参数类型为一个 void * 返回值类型为int
typedef void *(*pfn_co_routine_t)( void * );// 基本同上
//2.co_routine
int co_create( stCoRoutine_t **co,const stCoRoutineAttr_t *attr,void *(*routine)(void*),void *arg );
/*
线程create函数,用来创建创建一个线程,注意和线程不同,create只会创建协程,不会去运行协程。
stCoRoutine_t **co 当前协程 调用函数之后会对co进行赋值。
const stCoRoutineAttr_t *attr 使用哪个栈进行分配,以及分配的大小。传参不为NULL的话,cIsShareStack会赋值true。
void *(*routine)(void*) 协程调用的函数
void *arg 协程调用的函数 使用的参数 类似于线程的用法。
*/
void co_resume( stCoRoutine_t *co );//运行当前的协程,协程加入调用栈中,然后调用co_swap,交换,使进程/线程 运行当前协程
void co_yield( stCoRoutine_t *co );//作用同下
void co_yield_ct();
/*ct = current thread
让出协程,调用上一个入栈的协程。除非加入事件到时间轮中,不然当前协程不会再次运行。
底层调用co_yield_env。 libco协程是按照调用栈的顺序运行的,
因此传参的co其实是没用的x co_yield co_yield_ct co_yield_env 作用一样。
*/
void co_release( stCoRoutine_t *co );//调用co_free 释放内存
stCoRoutine_t *co_self(); //返回当前协程 其实就是调用栈栈顶的协程。
int co_poll( stCoEpoll_t *ctx,struct pollfd fds[], nfds_t nfds, int timeout_ms );
/*
调用了co_poll_inner
主要的作用为将需要监听的事件加入时间轮中,并让出协程。以及在事件触发后恢复函数执行,清理添加的事件。
stCoEpoll_t *ctx 当前协成,会使用协成中的参数
struct pollfd fds[] 时间数组
nfds_t nfds 数组大小
int timeout_ms 定时时间
*/
void co_eventloop( stCoEpoll_t *ctx,pfn_co_eventloop_t pfn,void *arg );
/*
主要功能为对时间进行轮询,不断调用epoll,超时事件则运行对应的协程。
stCoEpoll_t *ctx 存储定时事件
pfn_co_eventloop_t pfn,void *arg
if( pfn )
{
if( -1 == pfn( arg ) )
{
break;
}
}
函数中使用这个两个参数用来检测是否推出函数,通常为NULL,NULL。
*/
//3.specific
int co_setspecific( pthread_key_t key, const void *value );//设置key对应的value。
void * co_getspecific( pthread_key_t key );//获取key对应的value
//4.event
stCoEpoll_t * co_get_epoll_ct(); //ct = current thread 获取环境中存储定时事件的结构体
//5.hook syscall ( poll/read/write/recv/send/recvfrom/sendto )
void co_enable_hook_sys(); //修改当前协程的cEnableSysHook属性为true
void co_disable_hook_sys(); //修改当前协程的cEnableSysHook属性为false
bool co_is_enable_sys_hook(); //查询当前协程的cEnableSysHook属性
//6.sync
struct stCoCond_t;//信号量结构体 存储timewait添加的事件
stCoCond_t *co_cond_alloc();//分配内存
int co_cond_free( stCoCond_t * cc );//释放内存
int co_cond_signal( stCoCond_t * );//添加最近一次入栈的timedwait事件到活动事件中,co_eventloop轮询时会运行协程。
int co_cond_broadcast( stCoCond_t * );//广播 添加所有timewait事件。
int co_cond_timedwait( stCoCond_t *,int timeout_ms );//定时时间添加到epoll中,非定时事件添加到栈中。事件触发后会删除事件。
//7.share stack
stShareStack_t* co_alloc_sharestack(int iCount, int iStackSize);//分配共享栈内存
//8.init envlist for hook get/set env
void co_set_env_list( const char *name[],size_t cnt);//初始化环境变量
void co_log_err( const char *fmt,... );//错误日志
#endif
个人理解:co_routine.h文件的作用主要是声明一些结构体和函数,用于使用库时调用。后续会介绍协成如何管理,调用栈+时间轮。以及libco的hook,co_swap的实现,方便开发者的闭包实现,个人分析,如有不足,欢迎指出。