天天看点

co_routine.h分析

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的实现,方便开发者的闭包实现,个人分析,如有不足,欢迎指出。

继续阅读