mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-30 02:58:26 +08:00
improve emitter
This commit is contained in:
parent
ddc41b69a3
commit
ce8201ee49
@ -2,6 +2,7 @@
|
||||
|
||||
2021/12/31
|
||||
* fscript允许重载print函数。
|
||||
* 修复emitter的事件中删除事件同时递归触发事件导致emitter不正常的问题(感谢zxc3489和智明提供补丁)
|
||||
|
||||
2021/12/29
|
||||
* 修复 fscript 中 unset 的问题。
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"]
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user