rework widget pool

This commit is contained in:
xianjimli 2019-01-16 11:38:31 +08:00
parent fc3554ee3d
commit b04cafeb24
11 changed files with 515 additions and 150 deletions

View File

@ -87,7 +87,7 @@ OS_PROJECTS=[]
if OS_NAME == 'Darwin':
OS_LIBS = ['stdc++', 'pthread', 'm', 'dl']
OS_LINKFLAGS='-framework Cocoa -framework QuartzCore -framework OpenGL -weak_framework Metal -weak_framework MetalKit'
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DWITH_WIDGET_POOL '
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DWITH_WIDGET_POOL=1000 '
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -D__APPLE__ -DHAS_PTHREAD -DMACOS -DENABLE_MEM_LEAK_CHECK '
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -DBGFX_CONFIG_RENDERER_METAL=1 '

View File

@ -31,9 +31,10 @@
#include "base/input_method.h"
#include "base/image_manager.h"
#include "base/window_manager.h"
#include "base/widget_animator_manager.h"
#include "base/widget_factory.h"
#include "base/assets_manager.h"
#include "base/widget_pool.h"
#include "base/widget_animator_manager.h"
#include "font_loader/font_loader_bitmap.h"
#ifdef WITH_SDL
@ -101,7 +102,9 @@ ret_t tk_init_internal(void) {
#endif /*WITH_TRUETYPE_FONT*/
return_value_if_fail(platform_prepare() == RET_OK, RET_FAIL);
#ifdef WITH_WIDGET_POOL
return_value_if_fail(widget_pool_set(widget_pool_create(WITH_WIDGET_POOL)) == RET_OK, RET_FAIL);
#endif /*WITH_WIDGET_POOL*/
return_value_if_fail(timer_init(time_now_ms) == RET_OK, RET_FAIL);
return_value_if_fail(idle_manager_set(idle_manager_create()) == RET_OK, RET_FAIL);
return_value_if_fail(input_method_set(input_method_create()) == RET_OK, RET_FAIL);
@ -161,6 +164,11 @@ ret_t tk_deinit_internal(void) {
locale_info_destroy(locale_info());
locale_info_set(NULL);
#ifdef WITH_WIDGET_POOL
widget_pool_destroy(widget_pool());
widget_pool_set(NULL);
#endif /*WITH_WIDGET_POOL*/
assets_manager_destroy(assets_manager());
assets_manager_set(NULL);

View File

@ -29,6 +29,7 @@
#include "base/widget.h"
#include "base/layout.h"
#include "base/main_loop.h"
#include "base/widget_pool.h"
#include "base/system_info.h"
#include "base/widget_vtable.h"
#include "base/image_manager.h"
@ -36,7 +37,6 @@
#include "base/widget_animator_manager.h"
#include "base/widget_animator_factory.h"
static ret_t widget_reset(widget_t* widget);
static ret_t widget_do_destroy(widget_t* widget);
static ret_t widget_destroy_sync(widget_t* widget);
static ret_t widget_destroy_async(widget_t* widget);
@ -1398,52 +1398,6 @@ uint32_t widget_add_timer(widget_t* widget, timer_func_t on_timer, uint32_t dura
return id;
}
static ret_t widget_reset(widget_t* widget) {
if (widget->name != NULL) {
widget->name[0] = '\0';
}
if (widget->animation != NULL) {
widget->animation[0] = '\0';
}
if (widget->style != NULL) {
widget->style[0] = '\0';
}
if (widget->tr_text != NULL) {
widget->tr_text[0] = '\0';
}
widget->floating = FALSE;
widget->auto_created = FALSE;
widget->parent = NULL;
widget->target = NULL;
widget->emitter = NULL;
widget->children = NULL;
widget->key_target = NULL;
widget->self_layout = NULL;
widget->grab_widget = NULL;
widget->custom_props = NULL;
widget->children_layout = NULL;
return RET_OK;
}
static ret_t widget_recycle(widget_t* widget) {
return_value_if_fail(widget != NULL && widget->vt != NULL, RET_BAD_PARAMS);
if (widget->vt->recycle != NULL) {
if (widget->vt->recycle(widget) == RET_OK) {
widget_reset(widget);
return RET_OK;
}
}
return RET_NOT_IMPL;
}
static ret_t widget_destroy_sync(widget_t* widget) {
event_t e = event_init(EVT_DESTROY, widget);
return_value_if_fail(widget != NULL && widget->vt != NULL, RET_BAD_PARAMS);
@ -1482,21 +1436,14 @@ static ret_t widget_destroy_sync(widget_t* widget) {
widget->destroying = FALSE;
if (widget_recycle(widget) != RET_OK) {
if (widget->vt->on_destroy) {
widget->vt->on_destroy(widget);
}
return widget_pool_destroy_widget(widget_pool(), widget);
}
TKMEM_FREE(widget->name);
TKMEM_FREE(widget->style);
TKMEM_FREE(widget->tr_text);
TKMEM_FREE(widget->animation);
widget_t* widget_create(widget_t* parent, const widget_vtable_t* vt, xy_t x, xy_t y, wh_t w,
wh_t h) {
return_value_if_fail(vt != NULL, NULL);
memset(widget, 0x00, sizeof(widget_t));
TKMEM_FREE(widget);
}
return RET_OK;
return widget_init(widget_pool_create_widget(widget_pool(), vt), parent, vt, x, y, w, h);
}
static ret_t widget_destroy_in_idle(const idle_info_t* info) {
@ -1635,18 +1582,6 @@ widget_t* widget_init(widget_t* widget, widget_t* parent, const widget_vtable_t*
return widget;
}
widget_t* widget_create(widget_t* parent, const widget_vtable_t* vt, xy_t x, xy_t y, wh_t w,
wh_t h) {
widget_t* widget = NULL;
return_value_if_fail(vt != NULL && vt->size >= sizeof(widget_t), NULL);
widget = TKMEM_ALLOC(vt->size);
return_value_if_fail(widget != NULL, NULL);
memset(widget, 0x00, vt->size);
return widget_init(widget, parent, vt, x, y, w, h);
}
ret_t widget_get_prop_default_value(widget_t* widget, const char* name, value_t* v) {
ret_t ret = RET_OK;
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);

View File

@ -65,7 +65,6 @@ typedef ret_t (*widget_set_prop_t)(widget_t* widget, const char* name, const val
typedef widget_t* (*widget_find_target_t)(widget_t* widget, xy_t x, xy_t y);
typedef widget_t* (*widget_create_t)(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*widget_on_destroy_t)(widget_t* widget);
typedef ret_t (*widget_recycle_t)(widget_t* widget);
struct _widget_vtable_t {
uint32_t size;
@ -92,7 +91,7 @@ struct _widget_vtable_t {
uint32_t is_keyboard : 1;
/**
* pool
* pool(pool0)
*/
uint32_t enable_pool : 1;
@ -117,7 +116,6 @@ struct _widget_vtable_t {
widget_on_remove_child_t on_remove_child;
widget_on_event_t on_event;
widget_find_target_t find_target;
widget_recycle_t recycle;
widget_on_destroy_t on_destroy;
};

232
src/base/widget_pool.c Normal file
View File

@ -0,0 +1,232 @@
/**
* File: widget_pool.c
* Author: AWTK Develop Team
* Brief: widget pool
*
* Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-01-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/darray.h"
#include "base/widget.h"
#include "base/widget_pool.h"
static widget_pool_t* s_widget_pool;
static ret_t widget_pool_reset_widget(widget_t* widget) {
if (widget->name != NULL) {
widget->name[0] = '\0';
}
if (widget->animation != NULL) {
widget->animation[0] = '\0';
}
if (widget->style != NULL) {
widget->style[0] = '\0';
}
if (widget->tr_text != NULL) {
widget->tr_text[0] = '\0';
}
widget->floating = FALSE;
widget->auto_created = FALSE;
widget->parent = NULL;
widget->target = NULL;
widget->emitter = NULL;
widget->children = NULL;
widget->key_target = NULL;
widget->self_layout = NULL;
widget->grab_widget = NULL;
widget->custom_props = NULL;
widget->children_layout = NULL;
return RET_OK;
}
static ret_t widget_pool_real_destroy_widget(widget_t* widget) {
if (widget->vt->on_destroy) {
widget->vt->on_destroy(widget);
}
TKMEM_FREE(widget->name);
TKMEM_FREE(widget->style);
TKMEM_FREE(widget->tr_text);
TKMEM_FREE(widget->animation);
memset(widget, 0x00, sizeof(widget_t));
TKMEM_FREE(widget);
return RET_OK;
}
static widget_t* widget_pool_real_create_widget(const widget_vtable_t* vt) {
widget_t* widget = TKMEM_ALLOC(vt->size);
return_value_if_fail(widget != NULL, NULL);
memset(widget, 0x00, vt->size);
widget->vt = vt;
return widget;
}
widget_pool_t* widget_pool(void) {
return s_widget_pool;
}
ret_t widget_pool_set(widget_pool_t* pool) {
s_widget_pool = pool;
return RET_OK;
}
widget_pool_t* widget_pool_create(uint32_t max_cache_nr) {
widget_pool_t* pool = TKMEM_ZALLOC(widget_pool_t);
return_value_if_fail(pool != NULL, NULL);
pool->max_cache_nr = max_cache_nr;
pool->cache = object_default_create();
if (pool->cache == NULL) {
TKMEM_FREE(pool);
pool = NULL;
}
return pool;
}
static widget_t* widget_pool_get(widget_pool_t* pool, const char* type) {
value_t v;
if (object_get_prop(pool->cache, type, &v) == RET_OK) {
darray_t* arr = (darray_t*)value_pointer(&v);
return (widget_t*)darray_pop(arr);
}
return NULL;
}
widget_t* widget_pool_create_widget(widget_pool_t* pool, const widget_vtable_t* vt) {
widget_t* widget = NULL;
return_value_if_fail(vt != NULL && vt->size >= sizeof(widget_t), NULL);
if (pool != NULL && vt->enable_pool) {
widget = widget_pool_get(pool, vt->type);
if (widget != NULL) {
pool->cache_nr--;
}
}
if (widget == NULL) {
widget = widget_pool_real_create_widget(vt);
}
return widget;
}
static ret_t widget_pool_put(widget_pool_t* pool, widget_t* widget) {
if (pool->cache_nr < pool->max_cache_nr && widget->vt->enable_pool) {
value_t v;
darray_t* arr = NULL;
const char* type = widget->vt->type;
if (object_get_prop(pool->cache, type, &v) == RET_OK) {
arr = (darray_t*)value_pointer(&v);
}
if (arr == NULL) {
arr = darray_create(10, (tk_destroy_t)widget_pool_real_destroy_widget, NULL);
return_value_if_fail(arr != NULL, RET_OOM);
value_set_pointer(&v, arr);
if (object_set_prop(pool->cache, type, &v) != RET_OK) {
darray_destroy(arr);
arr = NULL;
}
}
return darray_push(arr, widget);
} else {
return RET_FAIL;
}
}
ret_t widget_pool_destroy_widget(widget_pool_t* pool, widget_t* widget) {
ret_t ret = RET_FAIL;
return_value_if_fail(widget != NULL && widget->vt != NULL, RET_BAD_PARAMS);
if (pool != NULL) {
ret = widget_pool_put(pool, widget);
if (ret == RET_OK) {
pool->cache_nr++;
widget_pool_reset_widget(widget);
}
}
if (ret != RET_OK) {
ret = widget_pool_real_destroy_widget(widget);
}
return ret;
}
static ret_t widget_pool_on_visit_remove_cache(void* ctx, named_value_t* nv) {
darray_t* arr = (darray_t*)value_pointer(&(nv->value));
darray_destroy(arr);
value_set_pointer(&(nv->value), NULL);
return RET_REMOVE;
}
ret_t widget_pool_clear_cache(widget_pool_t* pool) {
return_value_if_fail(pool != NULL, RET_BAD_PARAMS);
object_foreach_prop(pool->cache, (tk_visit_t)widget_pool_on_visit_remove_cache, NULL);
pool->cache_nr = 0;
return RET_OK;
}
static ret_t widget_pool_on_visit_count(void* ctx, named_value_t* nv) {
int32_t* n = (int32_t*)ctx;
darray_t* arr = (darray_t*)value_pointer(&(nv->value));
*n += arr->size;
return RET_OK;
}
int32_t widget_pool_count(widget_pool_t* pool) {
int32_t n = 0;
return_value_if_fail(pool != NULL, 0);
object_foreach_prop(pool->cache, (tk_visit_t)widget_pool_on_visit_count, &n);
return n;
}
ret_t widget_pool_destroy(widget_pool_t* pool) {
return_value_if_fail(pool != NULL && pool->cache != NULL, RET_BAD_PARAMS);
widget_pool_clear_cache(pool);
object_unref(pool->cache);
TKMEM_FREE(pool);
return RET_OK;
}

127
src/base/widget_pool.h Normal file
View File

@ -0,0 +1,127 @@
/**
* File: widget_pool.h
* Author: AWTK Develop Team
* Brief: widget pool
*
* Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-01-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_WIDGET_POOL_H
#define TK_WIDGET_POOL_H
#include "tkc/object_default.h"
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @class widget_pool_t
*
* widget pool把销毁的控件缓存起来使
*
* *
* *
*
*/
typedef struct _widget_pool_t {
object_t* cache;
uint32_t cache_nr;
uint32_t max_cache_nr;
} widget_pool_t;
/**
* @method widget_pool
* widget pool对象
*
* @annotation ["constructor"]
* @return {widget_pool_t*} widget pool对象
*/
widget_pool_t* widget_pool(void);
/**
* @method widget_pool_set
* widget pool对象
*
* @param {widget_pool_t*} pool widget pool对象
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_pool_set(widget_pool_t* pool);
/**
* @method widget_pool_create
* widget pool对象
*
* @annotation ["constructor"]
* @param {uint32_t} max_cache_nr
*
* @return {widget_pool_t*} widget pool对象
*/
widget_pool_t* widget_pool_create(uint32_t max_cache_nr);
/**
* @method widget_pool_create_widget
* widget对象
*
* @param {widget_pool_t*} pool widget pool对象
* @param {const widget_vtable_t*} vt
*
* @return {widget_t}
*/
widget_t* widget_pool_create_widget(widget_pool_t* pool, const widget_vtable_t* vt);
/**
* @method widget_pool_destroy_widget
* widget对象
*
* @param {widget_pool_t*} pool widget pool对象
* @param {widget_t*} widget
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_pool_destroy_widget(widget_pool_t* pool, widget_t* widget);
/**
* @method widget_pool_clear_cache
*
* @param {widget_pool_t*} pool widget pool对象
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_pool_clear_cache(widget_pool_t* pool);
/**
* @method widget_pool_count
*
* @param {widget_pool_t*} pool widget pool对象
*
* @return {int32_t}
*/
int32_t widget_pool_count(widget_pool_t* pool);
/**
* @method widget_pool_destroy
* widget pool对象
* @param {widget_pool_t*} pool widget pool对象
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_pool_destroy(widget_pool_t* pool);
END_C_DECLS
#endif /*TK_WIDGET_POOL_H*/

View File

@ -172,33 +172,11 @@ static ret_t button_on_destroy(widget_t* widget) {
return button_remove_timer(widget);
}
#ifdef WITH_WIDGET_POOL
static array_t s_button_pool;
static ret_t button_recycle(widget_t* widget) {
button_t* button = BUTTON(widget);
button->repeat = 0;
button_remove_timer(widget);
return array_push(&s_button_pool, widget);
}
static button_t* button_alloc(void) {
if (s_button_pool.size > 0) {
return (button_t*)array_pop(&s_button_pool);
} else {
return TKMEM_ZALLOC(button_t);
}
}
#else
#define button_recycle NULL
#define button_alloc() TKMEM_ZALLOC(button_t)
#endif /*WITH_WIDGET_POOL*/
static const char* s_button_properties[] = {WIDGET_PROP_REPEAT, NULL};
static const widget_vtable_t s_button_vtable = {
.size = sizeof(button_t),
.type = WIDGET_TYPE_BUTTON,
.enable_pool = TRUE,
.create = button_create,
.clone_properties = s_button_properties,
.persistent_properties = s_button_properties,
@ -207,15 +185,16 @@ static const widget_vtable_t s_button_vtable = {
.get_prop = button_get_prop,
.get_prop_default_value = button_get_prop_default_value,
.on_destroy = button_on_destroy,
.recycle = button_recycle,
.on_paint_self = widget_on_paint_self_default};
widget_t* button_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
button_t* button = button_alloc();
widget_t* widget = WIDGET(button);
widget_t* widget = widget_create(parent, &s_button_vtable, x, y, w, h);
button_t* button = BUTTON(widget);
return_value_if_fail(button != NULL, NULL);
widget_init(widget, parent, &s_button_vtable, x, y, w, h);
button->repeat = 0;
button->repeat_nr = 0;
button->pressed = FALSE;
button->timer_id = TK_INVALID_ID;
return widget;

View File

@ -91,24 +91,6 @@ static ret_t image_set_prop(widget_t* widget, const char* name, const value_t* v
}
}
#ifdef WITH_WIDGET_POOL
static array_t s_image_pool;
static ret_t image_recycle(widget_t* widget) {
return array_push(&s_image_pool, widget);
}
static image_t* image_alloc(void) {
if (s_image_pool.size > 0) {
return (image_t*)array_pop(&s_image_pool);
} else {
return TKMEM_ZALLOC(image_t);
}
}
#else
#define image_recycle NULL
#define image_alloc() TKMEM_ZALLOC(image_t)
#endif /*WITH_WIDGET_POOL*/
static const char* s_image_clone_properties[] = {WIDGET_PROP_IMAGE, WIDGET_PROP_DRAW_TYPE,
WIDGET_PROP_SCALE_X, WIDGET_PROP_SCALE_Y,
WIDGET_PROP_ANCHOR_X, WIDGET_PROP_ANCHOR_Y,
@ -117,21 +99,20 @@ static const char* s_image_clone_properties[] = {WIDGET_PROP_IMAGE, WIDGET_
static const widget_vtable_t s_image_vtable = {.size = sizeof(image_t),
.type = WIDGET_TYPE_IMAGE,
.enable_pool = TRUE,
.clone_properties = s_image_clone_properties,
.create = image_create,
.on_destroy = image_base_on_destroy,
.recycle = image_recycle,
.on_event = image_base_on_event,
.on_paint_self = image_on_paint_self,
.set_prop = image_set_prop,
.get_prop = image_get_prop};
widget_t* image_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
image_t* image = image_alloc();
widget_t* widget = WIDGET(image);
widget_t* widget = widget_create(parent, &s_image_vtable, x, y, w, h);
image_t* image = IMAGE(widget);
return_value_if_fail(image != NULL, NULL);
widget_init(widget, parent, &s_image_vtable, x, y, w, h);
image_base_init(widget);
image->draw_type = IMAGE_DRAW_DEFAULT;

View File

@ -193,38 +193,19 @@ static ret_t label_set_prop(widget_t* widget, const char* name, const value_t* v
return RET_NOT_FOUND;
}
#ifdef WITH_WIDGET_POOL
static array_t s_label_pool;
static ret_t label_recycle(widget_t* widget) {
return array_push(&s_label_pool, widget);
}
static label_t* label_alloc(void) {
if (s_label_pool.size > 0) {
return (label_t*)array_pop(&s_label_pool);
} else {
return TKMEM_ZALLOC(label_t);
}
}
#else
#define label_recycle NULL
#define label_alloc() TKMEM_ZALLOC(label_t)
#endif /*WITH_WIDGET_POOL*/
static const widget_vtable_t s_label_vtable = {.size = sizeof(label_t),
.type = WIDGET_TYPE_LABEL,
.enable_pool = TRUE,
.create = label_create,
.set_prop = label_set_prop,
.get_prop = label_get_prop,
.recycle = label_recycle,
.on_paint_self = label_on_paint_self};
widget_t* label_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
label_t* label = label_alloc();
widget_t* widget = WIDGET(label);
widget_t* widget = widget_create(parent, &s_label_vtable, x, y, w, h);
label_t* label = LABEL(widget);
return_value_if_fail(label != NULL, NULL);
widget_init(widget, parent, &s_label_vtable, x, y, w, h);
label->length = -1;
return widget;

124
tests/widget_pool_test.cc Normal file
View File

@ -0,0 +1,124 @@
#include "gtest/gtest.h"
#include "base/widget_pool.h"
#include "widgets/label.h"
static const widget_vtable_t s_enable_vtable = {
.size = sizeof(widget_t), .type = "enable", .enable_pool = TRUE};
static const widget_vtable_t s_disable_vtable = {.size = sizeof(widget_t), .type = "disable"};
TEST(WidgetPool, basic) {
const widget_vtable_t* vt = &s_enable_vtable;
const widget_vtable_t* d_vt = &s_disable_vtable;
widget_pool_t* pool = widget_pool_create(5);
widget_t* e = widget_pool_create_widget(pool, vt);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 1);
e = widget_pool_create_widget(pool, vt);
ASSERT_EQ(pool->cache_nr, 0);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 1);
e = widget_pool_create_widget(pool, d_vt);
ASSERT_EQ(pool->cache_nr, 1);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 1);
ASSERT_EQ(pool->cache_nr, widget_pool_count(pool));
ASSERT_EQ(widget_pool_clear_cache(pool), RET_OK);
ASSERT_EQ(pool->cache_nr, 0);
ASSERT_EQ(pool->cache_nr, widget_pool_count(pool));
widget_pool_destroy(pool);
}
TEST(WidgetPool, enable) {
const widget_vtable_t* vt = &s_enable_vtable;
widget_pool_t* pool = widget_pool_create(5);
widget_t* e = widget_pool_create_widget(pool, vt);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 1);
e = widget_pool_create_widget(pool, vt);
ASSERT_EQ(pool->cache_nr, 0);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 1);
widget_pool_destroy(pool);
}
TEST(WidgetPool, disable) {
const widget_vtable_t* vt = &s_disable_vtable;
widget_pool_t* pool = widget_pool_create(5);
widget_t* e = widget_pool_create_widget(pool, vt);
ASSERT_EQ(widget_pool_destroy_widget(pool, e), RET_OK);
ASSERT_EQ(pool->cache_nr, 0);
widget_pool_destroy(pool);
}
TEST(WidgetPool, disable_nr) {
const widget_vtable_t* vt = &s_disable_vtable;
widget_pool_t* pool = widget_pool_create(5);
widget_t* widgets[100];
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
widgets[i] = widget_pool_create_widget(pool, vt);
ASSERT_EQ(pool->cache_nr, 0);
}
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
ASSERT_EQ(widget_pool_destroy_widget(pool, widgets[i]), RET_OK);
ASSERT_EQ(pool->cache_nr, 0);
}
widget_pool_destroy(pool);
}
TEST(WidgetPool, enable_nr) {
const widget_vtable_t* vt = &s_enable_vtable;
widget_t* widgets[100];
widget_pool_t* pool = widget_pool_create(ARRAY_SIZE(widgets));
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
widgets[i] = widget_pool_create_widget(pool, vt);
ASSERT_EQ(pool->cache_nr, 0);
}
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
ASSERT_EQ(widget_pool_destroy_widget(pool, widgets[i]), RET_OK);
ASSERT_EQ(pool->cache_nr, i + 1);
}
widget_pool_destroy(pool);
}
TEST(WidgetPool, enable_nr_limit) {
const widget_vtable_t* vt = &s_enable_vtable;
widget_t* widgets[100];
widget_pool_t* pool = widget_pool_create(10);
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
widgets[i] = widget_pool_create_widget(pool, vt);
ASSERT_EQ(pool->cache_nr, 0);
}
for (int32_t i = 0; i < ARRAY_SIZE(widgets); i++) {
ASSERT_EQ(widget_pool_destroy_widget(pool, widgets[i]), RET_OK);
if (i < pool->max_cache_nr) {
ASSERT_EQ(pool->cache_nr, i + 1);
} else {
ASSERT_EQ(pool->cache_nr, pool->max_cache_nr);
}
}
widget_pool_destroy(pool);
}