代码拉取完成,页面将自动刷新
同步操作将从 swoole/swoole-src 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Xinyu Zhu <xyzhu1120@gmail.com> |
| shiguangqi <shiguangqi2008@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "php_swoole.h"
#ifdef SW_COROUTINE
#include "coroutine.h"
#include "swoole_coroutine.h"
#include "zend_vm.h"
#include "zend_closures.h"
/* PHP 7.3 compatibility macro {{{*/
#ifndef ZEND_CLOSURE_OBJECT
# define ZEND_CLOSURE_OBJECT(func) (zend_object*)func->op_array.prototype
#endif
#ifndef GC_ADDREF
# define GC_ADDREF(ref) ++GC_REFCOUNT(ref)
# define GC_DELREF(ref) --GC_REFCOUNT(ref)
#endif/*}}}*/
#define TASK_SLOT \
((int)((ZEND_MM_ALIGNED_SIZE(sizeof(coro_task)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))))
#define SWCC(x) sw_current_context->x
coro_global COROG;
static coro_task* sw_get_current_task();
#if PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 2
static inline void sw_vm_stack_init(void)
{
uint32_t size = COROG.stack_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;
}
#else
#define sw_vm_stack_init zend_vm_stack_init
#endif
int coro_init(TSRMLS_D)
{
COROG.origin_vm_stack = EG(vm_stack);
COROG.origin_vm_stack_top = EG(vm_stack_top);
COROG.origin_vm_stack_end = EG(vm_stack_end);
COROG.coro_num = 0;
if (COROG.max_coro_num <= 0)
{
COROG.max_coro_num = DEFAULT_MAX_CORO_NUM;
}
if (COROG.stack_size <= 0)
{
COROG.stack_size = DEFAULT_STACK_SIZE;
}
COROG.require = 0;
COROG.active = 1;
SwooleWG.coro_timeout_list = swLinkedList_new(1, NULL);
coroutine_set_close(sw_coro_close);
return 0;
}
void coro_check(TSRMLS_D)
{
if (!COROG.require)
{
swoole_php_fatal_error(E_ERROR, "must be called in the coroutine.");
}
}
void coro_destroy(TSRMLS_D)
{
if (COROG.chan_pipe)
{
COROG.chan_pipe->close(COROG.chan_pipe);
efree(COROG.chan_pipe);
COROG.chan_pipe = NULL;
}
}
int php_coro_create(php_args *php_arg)
{
zend_fcall_info_cache *fci_cache = php_arg->fci_cache;
zval **argv = php_arg->argv;
int argc = php_arg->argc;
zval *retval = php_arg->retval;
void *post_callback = php_arg->post_callback;
void* params = php_arg->params;
int cid = coroutine_get_cid();
zend_function *func;
uint32_t i;
coro_task *task;
zend_vm_stack origin_vm_stack = EG(vm_stack);
zval *origin_vm_stack_top = EG(vm_stack_top);
zval *origin_vm_stack_end = EG(vm_stack_end);
func = fci_cache->function_handler;
sw_vm_stack_init();
zend_execute_data *call = (zend_execute_data *) (EG(vm_stack_top));
task = (coro_task *) EG(vm_stack_top);
EG(vm_stack_top) = (zval *) ((char *) call + 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);
#if PHP_MINOR_VERSION < 1
EG(scope) = func->common.scope;
#endif
for (i = 0; i < argc; ++i)
{
zval *target;
target = ZEND_CALL_ARG(call, i + 1);
ZVAL_COPY(target, argv[i]);
}
call->symbol_table = NULL;
EG(current_execute_data) = NULL;
if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE))
{
uint32_t call_info;
GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info = ZEND_CALL_CLOSURE;
ZEND_ADD_CALL_FLAG(call, call_info);
}
zend_init_execute_data(call, &func->op_array, retval);
task->cid = cid;
task->execute_data = call;
task->stack = EG(vm_stack);
task->vm_stack_top = EG(vm_stack_top);
task->vm_stack_end = EG(vm_stack_end);
task->origin_stack = origin_vm_stack;
task->origin_vm_stack_top = origin_vm_stack_top;
task->origin_vm_stack_end = origin_vm_stack_end;
task->start_time = time(NULL);
task->function = NULL;
task->is_yield = 0;
task->state = SW_CORO_RUNNING;
task->co = coroutine_get_by_id(cid);
COROG.call_stack[COROG.call_stack_size++] = task;
COROG.current_coro = task;
swTraceLog(SW_TRACE_COROUTINE, "Create coro id: %d, coro total count: %d, heap size: %zu", cid, COROG.coro_num, zend_memory_usage(0));
EG(current_execute_data) = task->execute_data;
EG(vm_stack) = task->stack;
EG(vm_stack_top) = task->vm_stack_top;
EG(vm_stack_end) = task->vm_stack_end;
COROG.require = 1;
zend_execute_ex(EG(current_execute_data) TSRMLS_CC);
coro_task *curr_task = (coro_task *) sw_get_current_task();
return 0;
}
void php_coro_create_callback(void *arg)
{
php_args *php_arg = (php_args *) arg;
php_coro_create(php_arg);
}
int sw_coro_create(zend_fcall_info_cache *fci_cache, zval **argv, int argc, zval *retval, void *post_callback,
void *params)
{
if (unlikely(COROG.coro_num >= COROG.max_coro_num) )
{
COROG.error = 1;
swWarn("exceed max number of coro_num %d, max_coro_num:%d", COROG.coro_num, COROG.max_coro_num);
return CORO_LIMIT;
}
php_args php_args;
php_args.fci_cache = fci_cache;
php_args.argv = argv;
php_args.argc = argc;
php_args.retval = retval;
php_args.post_callback = post_callback;
php_args.params = params;
COROG.error = 0;
COROG.coro_num++;
return coroutine_create(php_coro_create_callback, (void*) &php_args);
}
void sw_coro_save(zval *return_value, php_context *sw_current_context)
{
SWCC(current_coro_return_value_ptr) = return_value;
SWCC(current_execute_data) = EG(current_execute_data);
SWCC(current_vm_stack) = EG(vm_stack);
SWCC(current_vm_stack_top) = EG(vm_stack_top);
SWCC(current_vm_stack_end) = EG(vm_stack_end);
SWCC(current_task) = (coro_task *) sw_get_current_task();;
}
int sw_coro_resume(php_context *sw_current_context, zval *retval, zval *coro_retval)
{
coro_task *task = SWCC(current_task);
COROG.call_stack[COROG.call_stack_size++] = task;
COROG.current_coro = task;
swTraceLog(SW_TRACE_COROUTINE,"sw_coro_resume coro id %d", COROG.current_coro->cid);
task->state = SW_CORO_RUNNING;
EG(current_execute_data) = SWCC(current_execute_data);
EG(vm_stack) = SWCC(current_vm_stack);
EG(vm_stack_top) = SWCC(current_vm_stack_top);
EG(vm_stack_end) = SWCC(current_vm_stack_end);
COROG.require = 1;
if (EG(current_execute_data)->prev_execute_data->opline->result_type != IS_UNUSED)
{
ZVAL_COPY(SWCC(current_coro_return_value_ptr), retval);
}
coroutine_resume(task->co);
if (unlikely(EG(exception)))
{
sw_zval_ptr_dtor(&retval);
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
}
return CORO_END;
}
void sw_coro_yield()
{
coro_task *task = (coro_task *) sw_get_current_task();
COROG.call_stack_size--;
swTraceLog(SW_TRACE_COROUTINE,"coro_yield coro id %d", task->cid);
task->state = SW_CORO_YIELD;
task->is_yield = 1;
EG(vm_stack) = task->origin_stack;
EG(vm_stack_top) = task->origin_vm_stack_top;
EG(vm_stack_end) = task->origin_vm_stack_end;
coroutine_yield(task->co);
}
void sw_coro_close()
{
coro_task *task = (coro_task *) sw_get_current_task();
swTraceLog(SW_TRACE_COROUTINE,"coro_close coro id %d", task->cid);
if (!task->is_yield)
{
EG(vm_stack) = task->origin_stack;
EG(vm_stack_top) = task->origin_vm_stack_top;
EG(vm_stack_end) = task->origin_vm_stack_end;
}
else
{
EG(vm_stack) = COROG.origin_vm_stack;
EG(vm_stack_top) = COROG.origin_vm_stack_top;
EG(vm_stack_end) = COROG.origin_vm_stack_end;
}
COROG.call_stack_size--;
efree(task->stack);
COROG.coro_num--;
COROG.current_coro = NULL;
COROG.require = 0;
swTraceLog(SW_TRACE_COROUTINE, "close coro and %d remained. usage size: %zu. malloc size: %zu", COROG.coro_num, zend_memory_usage(0), zend_memory_usage(1));
}
int sw_get_current_cid()
{
if (unlikely(COROG.active == 0))
{
return -1;
}
else
{
coro_task* task = sw_get_current_task();
if (task)
{
return task->cid;
}
return -1;
}
}
static coro_task* sw_get_current_task()
{
return (COROG.call_stack_size > 0) ? COROG.call_stack[COROG.call_stack_size - 1] : NULL;
}
void coro_handle_timeout()
{
swLinkedList *timeout_list = SwooleWG.coro_timeout_list;
swTimer_node *tnode = NULL;
if (timeout_list != NULL && timeout_list->num > 0)
{
php_context *cxt = (php_context *) swLinkedList_pop(timeout_list);
while (cxt != NULL)
{
cxt->onTimeout(cxt);
cxt = (php_context *) swLinkedList_pop(timeout_list);
}
}
timeout_list = SwooleWG.delayed_coro_timeout_list;
if (likely(timeout_list != NULL))
{
swTimer_coro_callback *scc = (swTimer_coro_callback *) swLinkedList_pop(timeout_list);
while (scc != NULL)
{
php_context *context = (php_context *) scc->data;
if (unlikely(context->state == SW_CORO_CONTEXT_TERM))
{
efree(context);
efree(scc);
}
else
{
context->state = SW_CORO_CONTEXT_RUNNING;
tnode = SwooleG.timer.add(&SwooleG.timer, scc->ms, 0, scc, php_swoole_onTimeout);
if (tnode == NULL)
{
efree(scc);
swWarn("Addtimer coro failed.");
}
else
{
tnode->type = SW_TIMER_TYPE_CORO;
*scc->timeout_id = tnode->id;
}
}
scc = (swTimer_coro_callback *) swLinkedList_pop(timeout_list);
}
}
}
#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。