Skip to content

Latest commit

 

History

History
160 lines (121 loc) · 3.83 KB

全局变量STUDYG.md

File metadata and controls

160 lines (121 loc) · 3.83 KB

全局变量STUDYG

我们在上一节里面说到了需要使用epoll来实现协程的调度,实际上epoll也可以实现我们的sleep功能,我们现在来实现一下。首先,我们需要一个全局的epoll,我把我们今后会用到的全局变量保存在统一的一个结构体里面。我们在文件study.h里面定义这个结构体:

typedef struct
{
    stPoll_t poll;
} stGlobal_t;

目前,里面存放了stPoll_t结构体,这个结构体我们也在study.h里面进行定义:

typedef struct
{
    int epollfd;
    int ncap;
    struct epoll_event *events;
} stPoll_t;

因为我们使用了epoll_event,所以,我们需要在study.h里面引入头文件:

#include <sys/epoll.h>

其中,

epollfd用来保存我们创建的那个epollfd。

events是用来保存epoll返回的事件。

ncap是events数组的大小。

然后,我们新建一个文件src/core/base.cc,文件内容如下:

#include "study.h"

stGlobal_t StudyG;

然后,我们需要在文件study.h里面去声明这个变量在其他地方定义了:

extern stGlobal_t StudyG;

为什么我们不直接在文件study.h里面定义全局变量StudyG呢?因为,如果我们在文件study.h里面定义了这个全局的变量,那么,如果头文件study.h被多个地方引入了,那么,编译器就会认为这个全局变量重复定义了,所以,我们需要在一个地方去定义它,然后在另一个地方声明这是一个外部变量。

因为我们增加了一个需要被编译到的源文件,所以我们需要修改我们的config.m4文件:

study_source_file="\
    study.cc \
    study_coroutine.cc \
    study_coroutine_util.cc \
    src/coroutine/coroutine.cc \
    src/coroutine/context.cc \
    ${STUDY_ASM_DIR}make_${STUDY_CONTEXT_ASM_FILE} \
    ${STUDY_ASM_DIR}jump_${STUDY_CONTEXT_ASM_FILE} \
    study_server_coro.cc \
    src/socket.cc \
    src/log.cc \
    src/error.cc \
    src/core/base.cc
"

然后,我们需要去修改我们的调度器代码:

int PHPCoroutine::scheduler()
{
    int timeout;
    size_t size;
    uv_loop_t *loop = uv_default_loop();

    StudyG.poll.epollfd = epoll_create(256);
    StudyG.poll.ncap = 16;
    size = sizeof(struct epoll_event) * StudyG.poll.ncap;
    StudyG.poll.events = (struct epoll_event *) malloc(size);
    memset(StudyG.poll.events, 0, size);

    while (loop->stop_flag == 0)
    {
        timeout = uv__next_timeout(loop);
        epoll_wait(StudyG.poll.epollfd, StudyG.poll.events, StudyG.poll.ncap, timeout);

        loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000;
        uv__run_timers(loop);

        if (uv__next_timeout(loop) < 0)
        {
            uv_stop(loop);
        }
    }

    return 0;
}

代码很简单,主要过程如下:

1、创建一个epollfd,然后保存在全局变量
2、在堆中为全局的StudyG.poll.events分配内存,默认的大小是16
3、把usleep替换为epoll_wait,时间是timeout

然后,我们需要重新生成一下我们的Makefile:

~/codeDir/cppCode/study # phpize --clean && phpize && ./configure

然后编译、安装扩展:

~/codeDir/cppCode/study # make && make install

编写测试代码:

<?php

Sgo(function ()
{
    var_dump("here1");
    Sco::sleep(0.5);
    var_dump("here2");
    Sco::sleep(1);
    var_dump("here3");
    Sco::sleep(1.5);
    var_dump("here4");
    Sco::sleep(2);
    var_dump("here5");
});

Sco::scheduler();

执行脚本:

~/codeDir/cppCode/study # php test.php 
string(5) "here1"
string(5) "here2"
string(5) "here3"
string(5) "here4"
string(5) "here5"
~/codeDir/cppCode/study # 

符合预期。

下一篇:定义协程化的Socket类