routine函数和结构体整理总结 libco源码分析、学习笔记

博客一级目录

二级目录——libco源码分析/学习笔记

由于routine代码分成了好几篇博客分析,然后现在在宏观上对函数和结构上进行小小的总结和整理。

一、常用的函数接口

以下函数是最上层的函数(供平时编程调用的函数)

int co_create( stCoRoutine_t **ppco,const stCoRoutineAttr_t *attr,pfn_co_routine_t pfn,void *arg );

创建一个协程,申请、初始化协程控制块;并负责协程环境的初始化。

参数1:协程控制块(结构体)指针的指针。

参数2:share stack(我认为是内存池,允许多个协程栈共享一块内存详见二级目录附带的知乎链接),可以写NULL表示不使用share stack。

参数3:函数指针:typedef void *(*pfn_co_routine_t)( void * );

参数4:参数3表示的函数的参数。void*类型。

返回值:始终返回0。

注意:主协程不需要create(由操作系统创建),也不需要resume(由操作系统赋予执行权),更不需要yield(return或exit)。一旦create了其它协程,它就会被create自动初始化。

void co_resume( stCoRoutine_t *co );

执行一个协程(交换执行权限,执行co,阻塞当前协程)。如果co是第一次执行会自动提前初始化上下文。

参数1:协程控制块指针。表示要执行的协程。

void co_yield_ct();

用于子协程主动交出执行权。

void co_yield( stCoRoutine_t *co);

剥夺co所在线程正在执行的协程的执行权。这里与void co_yield_ct();不一样的是:剥夺其它协程的执行权。这就允许协程时间片管理了(虽然可能用不到)。

void co_enable_hook_sys();

函数是用来打开 libco 的钩子标示,进行系统 io 函数的时候才会调用到 libco 的函数而不是原系统函数

int co_poll( stCoEpoll_t *ctx,struct pollfd fds[], nfds_t nfds, int timeout_ms );

下面这个函数功能相同(只是参数不同),co_poll直接调用并返回co_poll_inner的返回值,调用时将inner的参数5填为NULL。

 

int co_poll_inner( stCoEpoll_t *ctx,struct pollfd fds[], nfds_t nfds, int timeout, poll_pfn_t pollfunc);

我们对co_poll_inner进行解释:

功能:相当于epoll。要使co_poll工作必须在主协程中调用eventloop,否则无法检查事件超时。

参数1:eventloop控制块指针。因为poll要跟eventloop搭配。

参数2:监听的句柄数组,struct pollfd是Linux  poll用到的数据结构。

参数3:用于标记数组fds中的结构体元素的总数量。

参数4:超时时间ms,若此参数不为空,则此时间不仅仅被加入到epoll中监听,还会被加入到事件轮中等待超时同样会转为active。

参数5:函数指针,超时(active)事件。定义如下:

typedef int (*poll_pfn_t)(struct pollfd fds[], nfds_t nfds, int timeout);

简单的例子见下:

#include "co_routine.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <stack>

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>

#include <sys/epoll.h>
#ifdef __FreeBSD__
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#endif

#include<iostream>
using namespace std;

struct task_t
{
    stCoRoutine_t *co;
    int epFd;
};
typedef struct task_t task_t;

int myErrorOperate(char const * const error_str,int error_line,int error_exit=1)
{
    perror(error_str);
    printf("%d\n",error_line);
    if(error_exit==1)
        exit(1);
    return 0;
}
int co_accept(int fd, struct sockaddr *addr, socklen_t *len );
static void* mcoListen(void *arg_co)
{
   // task_t &co=*(task_t*)arg_co;
    co_enable_hook_sys();
    int lsEpFd;
    lsEpFd=epoll_create(100);
    if(lsEpFd<0)
    {
        myErrorOperate("create listen_epfd err",__LINE__);//exit
    }
    int lsSocketFd;
    if((lsSocketFd=socket(AF_INET,SOCK_STREAM,0))<0)
    {
   //     free(lsEpFd);
        myErrorOperate("create listen_socket fd err.",__LINE__);//exit
    }
    //set socket opt
    int ret,val=1;
    ret=setsockopt(lsSocketFd,SOL_SOCKET,SO_REUSEADDR,(void*)&val,sizeof(val));
        //reuse addr
    if(ret<0)
    {
        myErrorOperate("set SO_REUSEADDR err.",__LINE__,0);
    }

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(sockaddr_in));
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr=INADDR_ANY;
    saddr.sin_port=htons(8001);
    ret=bind(lsSocketFd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in));
    if(ret<0)
    {
        myErrorOperate("lsten socket bind err.",__LINE__,1);//exit
    }
    ret=listen(lsSocketFd,1024);//backlog
    if(ret<0)
    {
        myErrorOperate("listen err.",__LINE__,1);//exit
    }

    cout<<"Accepting connections..."<<endl;
    socklen_t saddrLen;
    for(;;)
    {
        saddrLen=sizeof(saddr);
        ret=co_accept(lsSocketFd,(struct sockaddr*)&saddr,&saddrLen);
       if(ret<0)//每次poll超时后都需要重新加入。
        {
            struct pollfd pf={0};
            pf.fd=ret;              //关心epoll事件
            pf.events=(POLLIN|POLLERR|POLLHUP);
            co_poll(co_get_epoll_ct(),&pf,1,1000);//yield   同时关心epoll事件,和1000ms的超时事件
        }
        if(ret>0)
        {
            cout<<ret<<endl;
        }
    }
}
void * print(void *args)
{
    co_enable_hook_sys();
    for(;;)
    {
        cout<<"time 0.5"<<endl;
        struct pollfd pf={0};//不关心epoll时间,只关心时间轮超时事件。
        co_poll(co_get_epoll_ct(),&pf,1,500);//500ms打印一次
    }
}
int main() {
    task_t coLs;
    stCoRoutine_t *time;
    co_create(&time,NULL,print,NULL);
    co_resume(time);//启动0.5s计时打印函数

    co_create(&(coLs.co),NULL,mcoListen,&coLs);
    co_resume(coLs.co);//启动接受连接函数,接受任何连接请求,打印sokecfd,然后不做任何事情
    cout<<"listen co init complete."<<endl;
    co_eventloop(co_get_epoll_ct(),0,0);
}

co_epoll系列

co_epoll_create();

co_epoll_ctl();

co_epoll_wait();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值