1 Star 0 Fork 0

nhky / swoole-src

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
swoole_timer.cc 11.89 KB
一键复制 编辑 原始数据 按行查看 历史
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| Copyright (c) 2012-2015 The Swoole Group |
+----------------------------------------------------------------------+
| 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: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "php_swoole_cxx.h"
#include "swoole_server.h"
#include "ext/spl/spl_array.h"
using swoole::Timer;
using swoole::TimerNode;
using zend::Function;
zend_class_entry *swoole_timer_ce;
static zend_object_handlers swoole_timer_handlers;
static zend_class_entry *swoole_timer_iterator_ce;
static struct {
bool enable_coroutine_isset;
bool enable_coroutine;
} settings;
SW_EXTERN_C_BEGIN
static PHP_FUNCTION(swoole_timer_set);
static PHP_FUNCTION(swoole_timer_after);
static PHP_FUNCTION(swoole_timer_tick);
static PHP_FUNCTION(swoole_timer_exists);
static PHP_FUNCTION(swoole_timer_info);
static PHP_FUNCTION(swoole_timer_stats);
static PHP_FUNCTION(swoole_timer_list);
static PHP_FUNCTION(swoole_timer_clear);
static PHP_FUNCTION(swoole_timer_clear_all);
SW_EXTERN_C_END
// clang-format off
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_void, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_set, 0, 0, 1)
ZEND_ARG_ARRAY_INFO(0, settings, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_after, 0, 0, 2)
ZEND_ARG_INFO(0, ms)
ZEND_ARG_CALLABLE_INFO(0, callback, 0)
ZEND_ARG_VARIADIC_INFO(0, params)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_tick, 0, 0, 2)
ZEND_ARG_INFO(0, ms)
ZEND_ARG_CALLABLE_INFO(0, callback, 0)
ZEND_ARG_VARIADIC_INFO(0, params)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_exists, 0, 0, 1)
ZEND_ARG_INFO(0, timer_id)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_info, 0, 0, 1)
ZEND_ARG_INFO(0, timer_id)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_timer_clear, 0, 0, 1)
ZEND_ARG_INFO(0, timer_id)
ZEND_END_ARG_INFO()
static const zend_function_entry swoole_timer_methods[] =
{
ZEND_FENTRY(set, ZEND_FN(swoole_timer_set), arginfo_swoole_timer_set, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(tick, ZEND_FN(swoole_timer_tick), arginfo_swoole_timer_tick, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(after, ZEND_FN(swoole_timer_after), arginfo_swoole_timer_after, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(exists, ZEND_FN(swoole_timer_exists), arginfo_swoole_timer_exists, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(info, ZEND_FN(swoole_timer_info), arginfo_swoole_timer_info, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(stats, ZEND_FN(swoole_timer_stats), arginfo_swoole_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(list, ZEND_FN(swoole_timer_list), arginfo_swoole_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(clear, ZEND_FN(swoole_timer_clear), arginfo_swoole_timer_clear, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_FENTRY(clearAll, ZEND_FN(swoole_timer_clear_all), arginfo_swoole_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END
};
// clang-format on
void php_swoole_timer_minit(int module_number) {
SW_INIT_CLASS_ENTRY(swoole_timer, "Swoole\\Timer", "swoole_timer", nullptr, swoole_timer_methods);
SW_SET_CLASS_CREATE(swoole_timer, sw_zend_create_object_deny);
SW_INIT_CLASS_ENTRY_BASE(swoole_timer_iterator,
"Swoole\\Timer\\Iterator",
"swoole_timer_iterator",
nullptr,
nullptr,
spl_ce_ArrayIterator);
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "set", CG(function_table), "swoole_timer_set");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "after", CG(function_table), "swoole_timer_after");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "tick", CG(function_table), "swoole_timer_tick");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "exists", CG(function_table), "swoole_timer_exists");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "info", CG(function_table), "swoole_timer_info");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "stats", CG(function_table), "swoole_timer_stats");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "list", CG(function_table), "swoole_timer_list");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "clear", CG(function_table), "swoole_timer_clear");
SW_FUNCTION_ALIAS(&swoole_timer_ce->function_table, "clearAll", CG(function_table), "swoole_timer_clear_all");
SW_REGISTER_LONG_CONSTANT("SWOOLE_TIMER_MIN_MS", SW_TIMER_MIN_MS);
SW_REGISTER_DOUBLE_CONSTANT("SWOOLE_TIMER_MIN_SEC", SW_TIMER_MIN_SEC);
SW_REGISTER_LONG_CONSTANT("SWOOLE_TIMER_MAX_MS", SW_TIMER_MAX_MS);
SW_REGISTER_DOUBLE_CONSTANT("SWOOLE_TIMER_MAX_SEC", SW_TIMER_MAX_SEC);
}
static void php_swoole_timer_dtor(TimerNode *tnode) {
Function *fci = (Function *) tnode->data;
sw_zend_fci_params_discard(&fci->fci);
sw_zend_fci_cache_discard(&fci->fci_cache);
efree(fci);
}
bool php_swoole_timer_clear(TimerNode *tnode) {
return swoole_timer_del(tnode);
}
bool php_swoole_timer_clear_all() {
if (UNEXPECTED(!SwooleTG.timer)) {
return false;
}
size_t num = SwooleTG.timer->count(), index = 0;
TimerNode **list = (TimerNode **) emalloc(num * sizeof(TimerNode *));
for (auto &kv : SwooleTG.timer->get_map()) {
TimerNode *tnode = kv.second;
if (tnode->type == TimerNode::TYPE_PHP) {
list[index++] = tnode;
}
}
while (index--) {
swoole_timer_del(list[index]);
}
efree(list);
return true;
}
static void php_swoole_onTimeout(Timer *timer, TimerNode *tnode) {
Function *fci = (Function *) tnode->data;
bool enable_coroutine = settings.enable_coroutine_isset ? settings.enable_coroutine : SwooleG.enable_coroutine;
if (UNEXPECTED(!fci->call(nullptr, enable_coroutine))) {
php_swoole_error(E_WARNING, "%s->onTimeout handler error", ZSTR_VAL(swoole_timer_ce->name));
}
if (!tnode->interval || tnode->removed) {
php_swoole_timer_dtor(tnode);
}
}
static void php_swoole_timer_add(INTERNAL_FUNCTION_PARAMETERS, bool persistent) {
zend_long ms;
Function *fci = (Function *) ecalloc(1, sizeof(Function));
TimerNode *tnode;
ZEND_PARSE_PARAMETERS_START(2, -1)
Z_PARAM_LONG(ms)
Z_PARAM_FUNC(fci->fci, fci->fci_cache)
Z_PARAM_VARIADIC('*', fci->fci.params, fci->fci.param_count)
ZEND_PARSE_PARAMETERS_END_EX(goto _failed);
if (UNEXPECTED(ms < SW_TIMER_MIN_MS)) {
php_swoole_fatal_error(E_WARNING, "Timer must be greater than or equal to " ZEND_TOSTR(SW_TIMER_MIN_MS));
_failed:
efree(fci);
RETURN_FALSE;
}
// no server || user worker || task process with async mode
if (!sw_server() || swIsUserWorker() || (swIsTaskWorker() && sw_server()->task_enable_coroutine)) {
php_swoole_check_reactor();
}
tnode = swoole_timer_add(ms, persistent, php_swoole_onTimeout, fci);
if (UNEXPECTED(!tnode)) {
php_swoole_fatal_error(E_WARNING, "add timer failed");
goto _failed;
}
tnode->type = TimerNode::TYPE_PHP;
tnode->destructor = php_swoole_timer_dtor;
if (persistent) {
if (fci->fci.param_count > 0) {
uint32_t i;
zval *params = (zval *) ecalloc(fci->fci.param_count + 1, sizeof(zval));
for (i = 0; i < fci->fci.param_count; i++) {
ZVAL_COPY(&params[i + 1], &fci->fci.params[i]);
}
fci->fci.params = params;
} else {
fci->fci.params = (zval *) emalloc(sizeof(zval));
}
fci->fci.param_count += 1;
ZVAL_LONG(fci->fci.params, tnode->id);
} else {
sw_zend_fci_params_persist(&fci->fci);
}
sw_zend_fci_cache_persist(&fci->fci_cache);
RETURN_LONG(tnode->id);
}
static PHP_FUNCTION(swoole_timer_set) {
zval *zset = nullptr;
HashTable *vht = nullptr;
zval *ztmp;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(zset)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
vht = Z_ARRVAL_P(zset);
if (php_swoole_array_get_value(vht, "enable_coroutine", ztmp)) {
settings.enable_coroutine_isset = true;
settings.enable_coroutine = zval_is_true(ztmp);
}
}
static PHP_FUNCTION(swoole_timer_after) {
php_swoole_timer_add(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
}
static PHP_FUNCTION(swoole_timer_tick) {
php_swoole_timer_add(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
}
static PHP_FUNCTION(swoole_timer_exists) {
if (UNEXPECTED(!SwooleTG.timer)) {
RETURN_FALSE;
} else {
zend_long id;
TimerNode *tnode;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(id)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
tnode = swoole_timer_get(id);
RETURN_BOOL(tnode && !tnode->removed);
}
}
static PHP_FUNCTION(swoole_timer_info) {
if (UNEXPECTED(!SwooleTG.timer)) {
RETURN_FALSE;
} else {
zend_long id;
TimerNode *tnode;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(id)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
tnode = swoole_timer_get(id);
if (UNEXPECTED(!tnode)) {
RETURN_NULL();
}
array_init(return_value);
add_assoc_long(return_value, "exec_msec", tnode->exec_msec);
add_assoc_long(return_value, "interval", tnode->interval);
add_assoc_long(return_value, "round", tnode->round);
add_assoc_bool(return_value, "removed", tnode->removed);
}
}
static PHP_FUNCTION(swoole_timer_stats) {
array_init(return_value);
if (SwooleTG.timer) {
add_assoc_bool(return_value, "initialized", 1);
add_assoc_long(return_value, "num", SwooleTG.timer->count());
add_assoc_long(return_value, "round", SwooleTG.timer->get_round());
} else {
add_assoc_bool(return_value, "initialized", 0);
add_assoc_long(return_value, "num", 0);
add_assoc_long(return_value, "round", 0);
}
}
static PHP_FUNCTION(swoole_timer_list) {
zval zlist;
array_init(&zlist);
if (EXPECTED(SwooleTG.timer)) {
for (auto &kv : SwooleTG.timer->get_map()) {
TimerNode *tnode = kv.second;
if (tnode->type == TimerNode::TYPE_PHP) {
add_next_index_long(&zlist, tnode->id);
}
}
}
object_init_ex(return_value, swoole_timer_iterator_ce);
sw_zend_call_method_with_1_params(
return_value, swoole_timer_iterator_ce, &swoole_timer_iterator_ce->constructor, "__construct", nullptr, &zlist);
zval_ptr_dtor(&zlist);
}
static PHP_FUNCTION(swoole_timer_clear) {
if (UNEXPECTED(!SwooleTG.timer)) {
RETURN_FALSE;
} else {
zend_long id;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(id)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
TimerNode *tnode = swoole_timer_get(id);
if (!tnode || tnode->type != TimerNode::TYPE_PHP) {
RETURN_FALSE;
}
RETURN_BOOL(swoole_timer_del(tnode));
}
}
static PHP_FUNCTION(swoole_timer_clear_all) {
RETURN_BOOL(php_swoole_timer_clear_all());
}
1
https://gitee.com/nhky/swoole-src.git
git@gitee.com:nhky/swoole-src.git
nhky
swoole-src
swoole-src
master

搜索帮助