Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
study
提交
4563e0fb
S
study
项目概览
OpenDocCN
/
study
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
study
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
4563e0fb
编写于
7月 01, 2019
作者:
C
codinghuang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update the code
上级
5534930f
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
241 addition
and
3 deletion
+241
-3
README.md
README.md
+1
-0
config.m4
config.m4
+1
-0
docs/《PHP扩展开发》-协程-协程创建(七).md
docs/《PHP扩展开发》-协程-协程创建(七).md
+42
-0
docs/《PHP扩展开发》-协程-协程创建(六).md
docs/《PHP扩展开发》-协程-协程创建(六).md
+4
-2
include/asm_context.h
include/asm_context.h
+11
-0
include/context.h
include/context.h
+25
-0
include/coroutine.h
include/coroutine.h
+26
-0
src/coroutine/context.cc
src/coroutine/context.cc
+40
-0
src/coroutine/coroutine.cc
src/coroutine/coroutine.cc
+17
-0
study_coroutine.cc
study_coroutine.cc
+68
-1
study_coroutine.h
study_coroutine.h
+6
-0
未找到文件。
README.md
浏览文件 @
4563e0fb
...
...
@@ -28,3 +28,4 @@ PHP版本:7.3.5
[
11、协程创建(六)
](
./docs/《PHP扩展开发》-协程-协程创建(六).md
)
[
12、协程创建(七)
](
./docs/《PHP扩展开发》-协程-协程创建(七).md
)
\ No newline at end of file
config.m4
浏览文件 @
4563e0fb
...
...
@@ -51,6 +51,7 @@ if test "$PHP_STUDY" != "no"; then
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}
"
...
...
docs/《PHP扩展开发》-协程-协程创建(七).md
0 → 100644
浏览文件 @
4563e0fb
# 协程创建(七)
我们在上篇文章,成功的保存了主协程的上下文信息,现在,我们就需要为我们的任务函数创建协程了。
我们在
`PHPCoroutine::create`
中写入:
```
cpp
long
PHPCoroutine
::
create
(
zend_fcall_info_cache
*
fci_cache
,
uint32_t
argc
,
zval
*
argv
)
{
php_coro_args
php_coro_args
;
php_coro_args
.
fci_cache
=
fci_cache
;
php_coro_args
.
argv
=
argv
;
php_coro_args
.
argc
=
argc
;
save_task
(
get_task
());
return
Coroutine
::
create
(
create_func
,
(
void
*
)
&
php_coro_args
);
}
```
其中,
`PHPCoroutine::create_func`
是用来创建协程任务函数的。它是:
```
cpp
typedef
void
(
*
coroutine_func_t
)(
void
*
)
```
类型的函数指针。
而
`php_coro_args`
则是传递给
`create_func`
的参数。
OK,我们现在来实现一下
`PHPCoroutine::create_func`
。我们先在
`Study::PHPCoroutine`
类中声明一下这个方法:
```
cpp
protected:
static
void
create_func
(
void
*
arg
);
```
然后,我们在文件
`study_coroutine.cc`
中来实现这个函数:
```
cpp
```
docs/《PHP扩展开发》-协程-协程创建(六).md
浏览文件 @
4563e0fb
...
...
@@ -104,4 +104,7 @@ protected:
void
*
task
=
nullptr
;
```
这样,我们就实现了保存
`PHP`
协程栈的功能。
\ No newline at end of file
这样,我们就实现了保存
`PHP`
协程栈的功能。
[
下一篇:协程创建(七)
](
./《PHP扩展开发》-协程-协程创建(七).md
)
include/asm_context.h
0 → 100644
浏览文件 @
4563e0fb
#ifndef ASM_CONTEXT_H
#define ASM_CONTEXT_H
#include "study.h"
typedef
void
*
fcontext_t
;
intptr_t
jump_fcontext
(
fcontext_t
*
ofc
,
fcontext_t
nfc
,
intptr_t
vp
,
bool
preserve_fpu
=
false
);
fcontext_t
make_fcontext
(
void
*
sp
,
size_t
size
,
void
(
*
fn
)(
intptr_t
));
#endif
/* ASM_CONTEXT_H */
\ No newline at end of file
include/context.h
浏览文件 @
4563e0fb
#ifndef CONTEXT_H
#define CONTEXT_H
#include "asm_context.h"
typedef
fcontext_t
coroutine_context_t
;
typedef
void
(
*
coroutine_func_t
)(
void
*
);
namespace
Study
{
class
Context
{
public:
Context
(
size_t
stack_size
,
coroutine_func_t
fn
,
void
*
private_data
);
~
Context
();
bool
swap_in
();
bool
swap_out
();
static
void
context_func
(
void
*
arg
);
// coroutine entry function
protected:
coroutine_context_t
ctx_
;
coroutine_context_t
swap_ctx_
;
coroutine_func_t
fn_
;
char
*
stack_
;
uint32_t
stack_size_
;
void
*
private_data_
;
bool
end_
;
};
}
#endif
/* CONTEXT_H */
include/coroutine.h
浏览文件 @
4563e0fb
...
...
@@ -2,19 +2,45 @@
#define COROUTINE_H
#include "context.h"
#include <unordered_map>
namespace
Study
{
class
Coroutine
{
public:
static
std
::
unordered_map
<
long
,
Coroutine
*>
coroutines
;
static
void
*
get_current_task
();
static
long
create
(
coroutine_func_t
fn
,
void
*
args
=
nullptr
);
void
*
get_task
();
static
Coroutine
*
get_current
();
void
set_task
(
void
*
_task
);
protected:
Coroutine
*
origin
;
static
Coroutine
*
current
;
void
*
task
=
nullptr
;
static
size_t
stack_size
;
Context
ctx
;
long
cid
;
static
long
last_cid
;
Coroutine
(
coroutine_func_t
fn
,
void
*
private_data
)
:
ctx
(
stack_size
,
fn
,
private_data
)
{
cid
=
++
last_cid
;
coroutines
[
cid
]
=
this
;
}
inline
long
run
()
{
long
cid
=
this
->
cid
;
origin
=
current
;
current
=
this
;
ctx
.
swap_in
();
return
cid
;
}
};
}
...
...
src/coroutine/context.cc
0 → 100644
浏览文件 @
4563e0fb
#include "context.h"
#include "study.h"
using
Study
::
Context
;
Context
::
Context
(
size_t
stack_size
,
coroutine_func_t
fn
,
void
*
private_data
)
:
fn_
(
fn
),
stack_size_
(
stack_size
),
private_data_
(
private_data
)
{
#ifdef SW_CONTEXT_PROTECT_STACK_PAGE
protect_page_
=
0
;
#endif
end_
=
false
;
swap_ctx_
=
nullptr
;
stack_
=
(
char
*
)
malloc
(
stack_size_
);
void
*
sp
=
(
void
*
)
((
char
*
)
stack_
+
stack_size_
);
ctx_
=
make_fcontext
(
sp
,
stack_size_
,
(
void
(
*
)(
intptr_t
))
&
context_func
);
}
bool
Context
::
swap_in
()
{
jump_fcontext
(
&
swap_ctx_
,
ctx_
,
(
intptr_t
)
this
,
true
);
return
true
;
}
bool
Context
::
swap_out
()
{
jump_fcontext
(
&
ctx_
,
swap_ctx_
,
(
intptr_t
)
this
,
true
);
return
true
;
}
void
Context
::
context_func
(
void
*
arg
)
{
Context
*
_this
=
(
Context
*
)
arg
;
_this
->
fn_
(
_this
->
private_data_
);
_this
->
end_
=
true
;
_this
->
swap_out
();
}
\ No newline at end of file
src/coroutine/coroutine.cc
浏览文件 @
4563e0fb
...
...
@@ -3,6 +3,8 @@
using
Study
::
Coroutine
;
Coroutine
*
Coroutine
::
current
=
nullptr
;
long
Coroutine
::
last_cid
=
0
;
std
::
unordered_map
<
long
,
Coroutine
*>
Coroutine
::
coroutines
;
void
*
Coroutine
::
get_current_task
()
{
...
...
@@ -12,4 +14,19 @@ void* Coroutine::get_current_task()
void
*
Coroutine
::
get_task
()
{
return
task
;
}
Coroutine
*
Coroutine
::
get_current
()
{
return
current
;
}
void
Coroutine
::
set_task
(
void
*
_task
)
{
task
=
_task
;
}
long
Coroutine
::
create
(
coroutine_func_t
fn
,
void
*
args
)
{
return
(
new
Coroutine
(
fn
,
args
))
->
run
();
}
\ No newline at end of file
study_coroutine.cc
浏览文件 @
4563e0fb
...
...
@@ -12,7 +12,8 @@ long PHPCoroutine::create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval
php_coro_args
.
argv
=
argv
;
php_coro_args
.
argc
=
argc
;
save_task
(
get_task
());
return
0
;
return
Coroutine
::
create
(
create_func
,
(
void
*
)
&
php_coro_args
);
}
php_coro_task
*
PHPCoroutine
::
get_task
()
...
...
@@ -34,3 +35,69 @@ void PHPCoroutine::save_vm_stack(php_coro_task *task)
task
->
vm_stack_page_size
=
EG
(
vm_stack_page_size
);
task
->
execute_data
=
EG
(
current_execute_data
);
}
void
PHPCoroutine
::
create_func
(
void
*
arg
)
{
int
i
;
php_coro_args
*
php_arg
=
(
php_coro_args
*
)
arg
;
zend_fcall_info_cache
fci_cache
=
*
php_arg
->
fci_cache
;
zend_function
*
func
=
fci_cache
.
function_handler
;
zval
*
argv
=
php_arg
->
argv
;
int
argc
=
php_arg
->
argc
;
php_coro_task
*
task
;
zend_execute_data
*
call
;
zval
_retval
,
*
retval
=
&
_retval
;
vm_stack_init
();
// get a new php stack
call
=
(
zend_execute_data
*
)
(
EG
(
vm_stack_top
));
task
=
(
php_coro_task
*
)
EG
(
vm_stack_top
);
EG
(
vm_stack_top
)
=
(
zval
*
)
((
char
*
)
call
+
PHP_CORO_TASK_SLOT
*
sizeof
(
zval
));
call
=
zend_vm_stack_push_call_frame
(
ZEND_CALL_TOP_FUNCTION
|
ZEND_CALL_ALLOCATED
,
func
,
argc
,
fci_cache
.
called_scope
,
fci_cache
.
object
);
for
(
i
=
0
;
i
<
argc
;
++
i
)
{
zval
*
param
;
zval
*
arg
=
&
argv
[
i
];
param
=
ZEND_CALL_ARG
(
call
,
i
+
1
);
ZVAL_COPY
(
param
,
arg
);
}
call
->
symbol_table
=
NULL
;
EG
(
current_execute_data
)
=
call
;
save_vm_stack
(
task
);
task
->
co
=
Coroutine
::
get_current
();
task
->
co
->
set_task
((
void
*
)
task
);
if
(
func
->
type
==
ZEND_USER_FUNCTION
)
{
ZVAL_UNDEF
(
retval
);
EG
(
current_execute_data
)
=
NULL
;
zend_init_func_execute_data
(
call
,
&
func
->
op_array
,
retval
);
zend_execute_ex
(
EG
(
current_execute_data
));
}
zval_ptr_dtor
(
retval
);
}
void
PHPCoroutine
::
vm_stack_init
(
void
)
{
uint32_t
size
=
DEFAULT_PHP_STACK_PAGE_SIZE
;
zend_vm_stack
page
=
(
zend_vm_stack
)
emalloc
(
size
);
page
->
top
=
ZEND_VM_STACK_ELEMENTS
(
page
);
page
->
end
=
(
zval
*
)
((
char
*
)
page
+
size
);
page
->
prev
=
NULL
;
EG
(
vm_stack
)
=
page
;
EG
(
vm_stack
)
->
top
++
;
EG
(
vm_stack_top
)
=
EG
(
vm_stack
)
->
top
;
EG
(
vm_stack_end
)
=
EG
(
vm_stack
)
->
end
;
EG
(
vm_stack_page_size
)
=
size
;
}
study_coroutine.h
浏览文件 @
4563e0fb
...
...
@@ -4,6 +4,9 @@
#include "php_study.h"
#include "coroutine.h"
#define DEFAULT_PHP_STACK_PAGE_SIZE 8192
#define PHP_CORO_TASK_SLOT ((int)((ZEND_MM_ALIGNED_SIZE(sizeof(php_coro_task)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))))
struct
php_coro_args
{
zend_fcall_info_cache
*
fci_cache
;
...
...
@@ -19,6 +22,7 @@ struct php_coro_task
zend_vm_stack
vm_stack
;
// current coroutine stack pointer
size_t
vm_stack_page_size
;
zend_execute_data
*
execute_data
;
// current coroutine stack frame
Study
::
Coroutine
*
co
;
};
namespace
Study
...
...
@@ -34,6 +38,8 @@ protected:
static
void
save_task
(
php_coro_task
*
task
);
static
void
save_vm_stack
(
php_coro_task
*
task
);
static
php_coro_task
*
get_task
();
static
void
create_func
(
void
*
arg
);
static
void
vm_stack_init
(
void
);
};
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录