add object_locker and reimplement app_conf with object_locker

This commit is contained in:
xianjimli 2020-06-12 21:53:22 +08:00
parent 8eaa3d2797
commit ca19ceac4d
6 changed files with 323 additions and 68 deletions

View File

@ -1,8 +1,10 @@
# 最新动态
* 2020/06/11
* 2020/06/12
* 增加 app\_conf\_set\_wstr/app\_conf\_get\_wstr
* 完善 window\_manager\_back\_to\_home 对软键盘窗口的处理。
* 增加 object\_locker 对 object 进行装饰,提供互斥的功能。
* 用 app_conf 重新实现 object\_locker。
* 2020/06/11
* 完善 conf\_io支持#name/#size

View File

@ -22,18 +22,17 @@
#include "tkc/str.h"
#include "tkc/utf8.h"
#include "tkc/mutex.h"
#include "tkc/object_locker.h"
#include "conf_io/app_conf.h"
static object_t* s_conf;
static tk_mutex_t* s_conf_lock;
ret_t app_conf_set_instance(object_t* obj) {
return_value_if_fail(s_conf == NULL, RET_BAD_PARAMS);
return_value_if_fail(obj != NULL, RET_BAD_PARAMS);
s_conf = obj;
s_conf_lock = tk_mutex_create();
ENSURE(s_conf_lock != NULL);
s_conf = object_locker_create(obj);
ENSURE(s_conf != NULL);
return RET_OK;
}
@ -43,62 +42,25 @@ object_t* app_conf_get_instance(void) {
}
ret_t app_conf_save(void) {
ret_t ret = RET_FAIL;
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = object_exec(s_conf, "save", NULL);
tk_mutex_unlock(s_conf_lock);
return ret;
return object_exec(s_conf, "save", NULL);
}
ret_t app_conf_deinit(void) {
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
OBJECT_UNREF(s_conf);
tk_mutex_unlock(s_conf_lock);
tk_mutex_destroy(s_conf_lock);
s_conf_lock = NULL;
return RET_OK;
}
ret_t app_conf_set(const char* key, const value_t* v) {
ret_t ret = RET_FAIL;
return_value_if_fail(key != NULL && v != NULL, RET_BAD_PARAMS);
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = object_set_prop(s_conf, key, v);
tk_mutex_unlock(s_conf_lock);
return ret;
return object_set_prop(s_conf, key, v);
}
ret_t app_conf_get(const char* key, value_t* v) {
ret_t ret = RET_FAIL;
return_value_if_fail(key != NULL && v != NULL, RET_BAD_PARAMS);
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = object_get_prop(s_conf, key, v);
tk_mutex_unlock(s_conf_lock);
return ret;
return object_get_prop(s_conf, key, v);
}
bool_t app_conf_exist(const char* key) {
bool_t ret = FALSE;
return_value_if_fail(key != NULL, FALSE);
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, FALSE);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = object_has_prop(s_conf, key);
tk_mutex_unlock(s_conf_lock);
return ret;
return object_has_prop(s_conf, key);
}
ret_t app_conf_set_int(const char* key, int32_t v) {
@ -189,46 +151,42 @@ const char* app_conf_get_str(const char* key, const char* defval) {
uint32_t app_conf_on_changed(event_func_t on_event, void* ctx) {
uint32_t ret = TK_INVALID_ID;
return_value_if_fail(on_event != NULL, ret);
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, ret);
return_value_if_fail(s_conf != NULL, ret);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, ret);
ret = emitter_on(EMITTER(s_conf), EVT_PROP_CHANGED, on_event, ctx);
tk_mutex_unlock(s_conf_lock);
if (object_exec(s_conf, "lock", NULL) == RET_OK) {
ret = emitter_on(EMITTER(s_conf), EVT_PROP_CHANGED, on_event, ctx);
object_exec(s_conf, "unlock", NULL);
}
return ret;
}
ret_t app_conf_off_changed(uint32_t id) {
ret_t ret = RET_FAIL;
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(s_conf != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = emitter_off(EMITTER(s_conf), id);
tk_mutex_unlock(s_conf_lock);
if (object_exec(s_conf, "lock", NULL) == RET_OK) {
ret = emitter_off(EMITTER(s_conf), id);
object_exec(s_conf, "unlock", NULL);
}
return ret;
}
ret_t app_conf_off_changed_by_ctx(void* ctx) {
ret_t ret = RET_FAIL;
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(s_conf != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = emitter_off_by_ctx(EMITTER(s_conf), ctx);
tk_mutex_unlock(s_conf_lock);
if (object_exec(s_conf, "lock", NULL) == RET_OK) {
ret = emitter_off_by_ctx(EMITTER(s_conf), ctx);
object_exec(s_conf, "unlock", NULL);
}
return ret;
}
ret_t app_conf_remove(const char* key) {
ret_t ret = RET_FAIL;
return_value_if_fail(s_conf != NULL && s_conf_lock != NULL, RET_BAD_PARAMS);
return_value_if_fail(tk_mutex_lock(s_conf_lock) == RET_OK, RET_BAD_PARAMS);
ret = object_remove_prop(s_conf, key);
tk_mutex_unlock(s_conf_lock);
return ret;
return object_remove_prop(s_conf, key);
}
ret_t app_conf_get_wstr(const char* key, wchar_t* str, uint32_t max_size) {
@ -254,4 +212,3 @@ ret_t app_conf_set_wstr(const char* key, const wchar_t* v) {
return ret;
}

153
src/tkc/object_locker.c Normal file
View File

@ -0,0 +1,153 @@
/**
* File: object_locker.c
* Author: AWTK Develop Team
* Brief: decorate object with lock
*
* Copyright (c) 2020 - 2020 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:
* ================================================================
* 2020-06-12 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/value.h"
#include "tkc/utils.h"
#include "tkc/object_locker.h"
static ret_t object_locker_on_destroy(object_t* obj) {
object_locker_t* o = OBJECT_LOCKER(obj);
tk_mutex_destroy(o->mutex);
OBJECT_UNREF(o->obj);
return RET_OK;
}
static int32_t object_locker_compare(object_t* obj, object_t* other) {
object_locker_t* o = OBJECT_LOCKER(obj);
return object_compare(o->obj, other);
}
static ret_t object_locker_remove_prop(object_t* obj, const char* name) {
ret_t ret = RET_NOT_FOUND;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_remove_prop(o->obj, name);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static ret_t object_locker_set_prop(object_t* obj, const char* name, const value_t* v) {
ret_t ret = RET_NOT_FOUND;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_set_prop(o->obj, name, v);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static ret_t object_locker_get_prop(object_t* obj, const char* name, value_t* v) {
ret_t ret = RET_NOT_FOUND;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_get_prop(o->obj, name, v);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static ret_t object_locker_foreach_prop(object_t* obj, tk_visit_t on_prop, void* ctx) {
ret_t ret = RET_OK;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_foreach_prop(o->obj, on_prop, ctx);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static bool_t object_locker_can_exec(object_t* obj, const char* name, const char* args) {
bool_t ret = RET_OK;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_can_exec(o->obj, name, args);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static ret_t object_locker_exec(object_t* obj, const char* name, const char* args) {
ret_t ret = RET_OK;
object_locker_t* o = OBJECT_LOCKER(obj);
if (tk_str_eq(name, "lock")) {
return tk_mutex_lock(o->mutex);
} else if (tk_str_eq(name, "unlock")) {
return tk_mutex_unlock(o->mutex);
} else if (tk_mutex_lock(o->mutex) == RET_OK) {
ret = object_exec(o->obj, name, args);
tk_mutex_unlock(o->mutex);
}
return ret;
}
static const object_vtable_t s_object_locker_vtable = {.type = "object_locker",
.desc = "object_locker",
.size = sizeof(object_locker_t),
.is_collection = FALSE,
.on_destroy = object_locker_on_destroy,
.exec = object_locker_exec,
.can_exec = object_locker_can_exec,
.compare = object_locker_compare,
.get_prop = object_locker_get_prop,
.set_prop = object_locker_set_prop,
.remove_prop = object_locker_remove_prop,
.foreach_prop = object_locker_foreach_prop};
object_t* object_locker_create(object_t* obj) {
object_t* o = NULL;
object_locker_t* wrapper = NULL;
return_value_if_fail(obj != NULL, NULL);
o = object_create(&s_object_locker_vtable);
wrapper = OBJECT_LOCKER(o);
return_value_if_fail(wrapper != NULL, NULL);
wrapper->mutex = tk_mutex_create();
if (wrapper->mutex != NULL) {
wrapper->obj = object_ref(obj);
} else {
OBJECT_UNREF(wrapper->obj);
}
return o;
}
object_locker_t* object_locker_cast(object_t* obj) {
return_value_if_fail(obj != NULL && obj->vt == &s_object_locker_vtable, NULL);
return (object_locker_t*)(obj);
}

64
src/tkc/object_locker.h Normal file
View File

@ -0,0 +1,64 @@
/**
* File: object_locker.h
* Author: AWTK Develop Team
* Brief: decorate object with lock
*
* Copyright (c) 2020 - 2020 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:
* ================================================================
* 2020-06-20 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_OBJECT_LOCKER_H
#define TK_OBJECT_LOCKER_H
#include "tkc/mutex.h"
#include "tkc/object.h"
BEGIN_C_DECLS
/**
* @class object_locker_t
* @parent object_t
*
* object对象进行装饰访
*
*/
typedef struct _object_locker_t {
object_t object;
/*private*/
tk_mutex_t* mutex;
object_t* obj;
} object_locker_t;
/**
* @method object_locker_create
*
*
*
* @annotation ["constructor"]
*
* @param {object_t*} obj
*
* @return {object_t*} object对象
*
*/
object_t* object_locker_create(object_t* obj);
object_locker_t* object_locker_cast(object_t* obj);
#define OBJECT_LOCKER(obj) object_locker_cast(obj)
END_C_DECLS
#endif /*TK_OBJECT_LOCKER_H*/

View File

@ -34,7 +34,7 @@ TEST(Ini, group2) {
node = conf_node_find_child(doc->root, "world");
ASSERT_EQ(node != NULL, true);
ASSERT_STREQ(conf_node_get_name(node), "world");
ASSERT_EQ(conf_doc_get(doc, "#size", &v), RET_OK);
ASSERT_EQ(value_int(&v), 2);

View File

@ -0,0 +1,79 @@
#include "tkc/utils.h"
#include "tkc/object_locker.h"
#include "tkc/object_default.h"
#include "gtest/gtest.h"
#include <stdlib.h>
#include <string>
using std::string;
static ret_t event_dump(void* ctx, event_t* e) {
string& str = *(string*)ctx;
if (e->type == EVT_PROP_WILL_CHANGE || e->type == EVT_PROP_CHANGED) {
prop_change_event_t* evt = (prop_change_event_t*)e;
str += evt->name;
str += ":";
} else if (e->type == EVT_DESTROY) {
str += "destroy:";
}
return RET_OK;
}
static ret_t visit_dump(void* ctx, const void* data) {
string& str = *(string*)ctx;
const named_value_t* nv = (named_value_t*)data;
str += nv->name;
return RET_OK;
}
TEST(ObjectLocker, events) {
value_t v;
string log;
object_t* obj = object_default_create();
object_default_t* o = OBJECT_DEFAULT(obj);
obj = object_locker_create(obj);
emitter_on(EMITTER(obj), EVT_PROP_WILL_CHANGE, event_dump, &log);
emitter_on(EMITTER(obj), EVT_PROP_CHANGED, event_dump, &log);
emitter_on(EMITTER(obj), EVT_DESTROY, event_dump, &log);
ASSERT_EQ(object_set_prop(obj, "6", value_set_int(&v, 50)), RET_OK);
ASSERT_EQ(object_set_prop(obj, "8", value_set_int(&v, 50)), RET_OK);
OBJECT_UNREF(o);
OBJECT_UNREF(obj);
ASSERT_EQ(log, "6:6:8:8:destroy:");
}
TEST(ObjectLocker, basic) {
value_t v;
string log;
object_t* obj = object_default_create();
object_default_t* o = OBJECT_DEFAULT(obj);
obj = object_locker_create(obj);
ASSERT_EQ(object_set_prop(obj, "5", value_set_int(&v, 50)), RET_OK);
ASSERT_EQ(object_get_prop(obj, "5", &v), RET_OK);
ASSERT_EQ(value_int(&v), 50);
ASSERT_EQ(object_set_prop(obj, "6", value_set_int(&v, 60)), RET_OK);
ASSERT_EQ(object_get_prop(obj, "6", &v), RET_OK);
ASSERT_EQ(value_int(&v), 60);
log = "";
object_foreach_prop(obj, visit_dump, &log);
ASSERT_EQ(log, "56");
ASSERT_EQ(object_remove_prop(obj, "5"), RET_OK);
ASSERT_EQ(object_get_prop(obj, "3", &v), RET_NOT_FOUND);
ASSERT_EQ(object_remove_prop(obj, "3"), RET_NOT_FOUND);
OBJECT_UNREF(o);
OBJECT_UNREF(obj);
}