improve emitter

This commit is contained in:
lixianjing 2021-12-31 17:05:26 +08:00
parent ddc41b69a3
commit ce8201ee49
4 changed files with 59 additions and 18 deletions

View File

@ -2,6 +2,7 @@
2021/12/31
* fscript允许重载print函数。
* 修复emitter的事件中删除事件同时递归触发事件导致emitter不正常的问题感谢zxc3489和智明提供补丁
2021/12/29
* 修复 fscript 中 unset 的问题。

View File

@ -72,7 +72,7 @@ static ret_t emitter_remove(emitter_t* emitter, emitter_item_t* prev, emitter_it
return_value_if_fail(emitter != NULL && iter != NULL, RET_BAD_PARAMS);
if (emitter->curr_iter == iter) {
emitter->remove_curr_iter = TRUE;
iter->pending_remove = TRUE;
return RET_OK;
}
@ -111,6 +111,7 @@ ret_t emitter_remove_item(emitter_t* emitter, emitter_item_t* item) {
ret_t emitter_dispatch(emitter_t* emitter, event_t* e) {
ret_t ret = RET_OK;
emitter_item_t* emitter_curr_iter = NULL;
return_value_if_fail(emitter != NULL && e != NULL, RET_BAD_PARAMS);
if (!(e->time)) {
@ -120,7 +121,7 @@ ret_t emitter_dispatch(emitter_t* emitter, event_t* e) {
if (e->target == NULL) {
e->target = emitter;
}
emitter_curr_iter = emitter->curr_iter;
if (emitter->disable == 0 && emitter->items) {
emitter_item_t* iter = emitter->items;
@ -129,17 +130,15 @@ ret_t emitter_dispatch(emitter_t* emitter, event_t* e) {
if (iter->type == e->type) {
ret = iter->handler(iter->ctx, e);
if (ret == RET_STOP) {
emitter->curr_iter = NULL;
if (emitter->remove_curr_iter) {
emitter->remove_curr_iter = FALSE;
emitter->curr_iter = emitter_curr_iter;
if (iter->pending_remove) {
emitter_remove_item(emitter, iter);
}
return ret;
} else if (ret == RET_REMOVE || emitter->remove_curr_iter) {
} else if (ret == RET_REMOVE || iter->pending_remove) {
emitter_item_t* next = iter->next;
emitter->curr_iter = NULL;
emitter->remove_curr_iter = FALSE;
emitter_remove_item(emitter, iter);
iter = next;
@ -150,8 +149,7 @@ ret_t emitter_dispatch(emitter_t* emitter, event_t* e) {
iter = iter->next;
}
}
emitter->curr_iter = NULL;
emitter->remove_curr_iter = FALSE;
emitter->curr_iter = emitter_curr_iter;
return RET_OK;
}
@ -240,7 +238,7 @@ static ret_t emitter_off_ex(emitter_t* emitter, tk_compare_t cmp, void* ctx) {
emitter_item_t* prev = emitter->items;
while (iter != NULL) {
if ((emitter->curr_iter != iter || !emitter->remove_curr_iter) && cmp(iter, ctx) == 0) {
if (!iter->pending_remove && cmp(iter, ctx) == 0) {
return emitter_remove(emitter, prev, iter);
}

View File

@ -36,6 +36,7 @@ struct _emitter_item_t {
event_func_t handler;
uint32_t tag;
bool_t pending_remove;
tk_destroy_t on_destroy;
void* on_destroy_ctx;
emitter_item_t* next;
@ -68,14 +69,6 @@ typedef struct _emitter_t {
*/
int32_t disable;
/**
* @property {bool_t} remove_curr_iter
* @annotation ["private"]
* emitter_off当前正在dispatch的回调函数
* remove_curr_iter为TRUE
* XXX: dispatch的回调函数RET_REMOVE是最好的选择
*/
bool_t remove_curr_iter;
/**
* @property {emitter_item_t*} curr_iter
* @annotation ["private"]

View File

@ -31,6 +31,26 @@ static ret_t on_remove_id(void* ctx, event_t* e) {
return RET_REMOVE;
}
static ret_t on_remove_and_dispatch(void* ctx, event_t* e) {
uint32_t type = *((uint32_t*)ctx);
emitter_t* emitter = (emitter_t*)e->target;
emitter_off_by_func(emitter, type, on_remove_and_dispatch, ctx);
emitter_dispatch_simple_event(emitter, type + 1);
return RET_OK;
}
static ret_t on_dispatch_and_remove(void* ctx, event_t* e) {
uint32_t type = *((uint32_t*)ctx);
emitter_t* emitter = (emitter_t*)e->target;
emitter_dispatch_simple_event(emitter, type + 1);
emitter_off_by_func(emitter, type, on_dispatch_and_remove, ctx);
return RET_OK;
}
static ret_t on_stop(void* ctx, event_t* e) {
uint32_t* p = (uint32_t*)ctx;
*p = *p + 1;
@ -179,6 +199,35 @@ TEST(Emitter, remove_in_func) {
emitter_destroy(emitter);
}
TEST(Emitter, remove_in_func2) {
event_t e;
uint32_t n = 0;
uint32_t id1 = 0;
uint32_t id2 = 0;
uint32_t id3 = 0;
uint32_t type = 12;
emitter_t* emitter = emitter_create();
e = event_init(type, emitter);
id1 = emitter_on(emitter, type, on_remove_and_dispatch, &type);
id2 = emitter_on(emitter, type + 1, on_event, &n);
ASSERT_EQ(emitter_dispatch(emitter, &e), RET_OK);
ASSERT_EQ(emitter_size(emitter), 1u);
ASSERT_EQ(emitter_find(emitter, id1) == NULL, true);
ASSERT_EQ(emitter_find(emitter, id2) != NULL, true);
id1 = emitter_on(emitter, type, on_dispatch_and_remove, &type);
id3 = emitter_on(emitter, type + 1, on_event, &n);
ASSERT_EQ(emitter_dispatch(emitter, &e), RET_OK);
ASSERT_EQ(emitter_size(emitter), 2u);
ASSERT_EQ(emitter_find(emitter, id1) == NULL, true);
ASSERT_EQ(emitter_find(emitter, id2) != NULL, true);
ASSERT_EQ(emitter_find(emitter, id3) != NULL, true);
emitter_destroy(emitter);
}
TEST(Emitter, remove_item) {
uint32_t i = 0;
uint32_t n = 5000;