mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-29 18:48:09 +08:00
add object_locker and reimplement app_conf with object_locker
This commit is contained in:
parent
8eaa3d2797
commit
ca19ceac4d
@ -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
|
||||
|
@ -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
153
src/tkc/object_locker.c
Normal 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
64
src/tkc/object_locker.h
Normal 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*/
|
@ -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);
|
||||
|
||||
|
79
tests/object_locker_test.cc
Normal file
79
tests/object_locker_test.cc
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user